json_decode কাস্টম ক্লাসে


90

StdClass ব্যতীত অন্য কোনও জিনিসে কোনও জসন স্ট্রিং ডিকোড করা সম্ভব?


4
এত বছর পরেও এ নিয়ে নতুন কিছু নেই?
ভিক্টর

আমি এমন একটি সমাধান পেয়েছি যা আমার জন্য কাজ করে stackoverflow.com/a/48838378/8138241
জেসন লিউ

উত্তর:


96

স্বয়ংক্রিয়ভাবে না। তবে আপনি এটি পুরানো ফ্যাশন রুটটি করতে পারেন।

$data = json_decode($json, true);

$class = new Whatever();
foreach ($data as $key => $value) $class->{$key} = $value;

বা বিকল্পভাবে, আপনি যে আরও স্বয়ংক্রিয় করতে পারেন:

class Whatever {
    public function set($data) {
        foreach ($data AS $key => $value) $this->{$key} = $value;
    }
}

$class = new Whatever();
$class->set($data);

সম্পাদনা : একটু অনুরাগী পাওয়া:

class JSONObject {
    public function __construct($json = false) {
        if ($json) $this->set(json_decode($json, true));
    }

    public function set($data) {
        foreach ($data AS $key => $value) {
            if (is_array($value)) {
                $sub = new JSONObject;
                $sub->set($value);
                $value = $sub;
            }
            $this->{$key} = $value;
        }
    }
}

// These next steps aren't necessary. I'm just prepping test data.
$data = array(
    "this" => "that",
    "what" => "who",
    "how" => "dy",
    "multi" => array(
        "more" => "stuff"
    )
);
$jsonString = json_encode($data);

// Here's the sweetness.
$class = new JSONObject($jsonString);
print_r($class);

4
আমি আপনাকে পরামর্শ চাই, কেবলমাত্র এটি মন্তব্য করার জন্য যে এটি নেস্টেড অবজেক্টগুলির সাথে কাজ করবে না (এসটিডিস্লাস বা রূপান্তরিত বস্তু ব্যতীত)
জাভিয়ের_ডমেনেক

36

আমরা আমাদের নিজস্ব মডেল ক্লাসে JSON অবজেক্টগুলিকে স্বয়ংক্রিয়ভাবে ম্যাপ করতে JsonMapper তৈরি করেছি । এটি নেস্টেড / চাইল্ড অবজেক্টের সাথে দুর্দান্ত কাজ করে।

এটি কেবল ম্যাপিংয়ের জন্য ডকব্লক টাইপ তথ্যের উপর নির্ভর করে যা বেশিরভাগ শ্রেণীর বৈশিষ্ট্যগুলিতে যাইহোক:

<?php
$mapper = new JsonMapper();
$contactObject = $mapper->map(
    json_decode(file_get_contents('http://example.org/contact.json')),
    new Contact()
);
?>

4
কি দারুন! এটা ঠিক আশ্চর্যজনক।
ভ্যাটহাইসন

আপনি OSL3 লাইসেন্স ব্যাখ্যা করতে পারেন? আমি যদি কোনও ওয়েবসাইটে জসনম্যাপার ব্যবহার করি তবে আমাকে অবশ্যই সেই ওয়েবসাইটটির উত্স কোডটি প্রকাশ করা উচিত? আমি বিক্রি করি এমন কোনও ডিভাইসে যদি আমি জসনম্যাপার কোডটিতে ব্যবহার করি, তবে অবশ্যই সেই ডিভাইসের কোডের সমস্তটি ওপেন সোর্স হওয়া উচিত?
এরিকপি

4
না, আপনি কেবল জসনম্যাপার নিজেই যে পরিবর্তনগুলি করেন তা প্রকাশ করতে হবে।
cweiske

29

আপনি এটি করতে পারেন - এটি একটি ক্লডজ তবে সম্পূর্ণ সম্ভব। যখন আমরা কাউচবেসে জিনিস সঞ্চয় করতে শুরু করি তখন আমাদের করতে হয়েছিল।

$stdobj = json_decode($json_encoded_myClassInstance);  //JSON to stdClass
$temp = serialize($stdobj);                   //stdClass to serialized

// Now we reach in and change the class of the serialized object
$temp = preg_replace('@^O:8:"stdClass":@','O:7:"MyClass":',$temp);

// Unserialize and walk away like nothing happend
$myClassInstance = unserialize($temp);   // Presto a php Class 

আমাদের মানদণ্ডগুলিতে এটি সমস্ত শ্রেণীর ভেরিয়েবলগুলির মাধ্যমে পুনরাবৃত্তি করার চেষ্টা করার চেয়ে দ্রুততর ছিল।

ক্যাভ্যাট: স্টেডক্লাস ব্যতীত নেস্টেড বস্তুর জন্য কাজ করবে না

সম্পাদনা করুন: ডেটা উত্সটি মনে রাখবেন, এটির দৃ recommended়ভাবে সুপারিশ করা হয় যে ঝুঁকিগুলির খুব যত্নশীল বিশ্লেষণ না করে আপনি ব্যবহারকারীদের কাছ থেকে এই অবিশ্বাস্য ডেটা করবেন না।


4
এটি এনক্যাপসুলেটেড সাবক্লাসগুলির সাথে কাজ করে। উদাহরণস্বরূপ { "a": {"b":"c"} }, যেখানে অবজেক্টটি aঅন্য শ্রেণীর এবং কেবল কোনও মিশুক অ্যারে নয়?
জে-রু

4
না, জেসন_ডেকোড উপ-অবজেক্টগুলি সহ স্টাডক্লাস অবজেক্ট তৈরি করে, যদি আপনি সেগুলিকে অন্য কিছু হতে চান তবে উপরের মতো প্রতিটি বস্তু নষ্ট করতে হবে।
জন পেটিট

আপনাকে ধন্যবাদ, আমি এটি যা কল্পনা করেছি
জে-রউ

কনস্ট্রাক্টরের প্যারামিটার রয়েছে এমন বস্তুগুলিতে এই সমাধানটি কীভাবে ব্যবহার করা যায়। আমি এটি কাজ করতে পারি না। আমি আশা করছিলাম যে কোনও ব্যক্তি প্যারামিটারগুলির সাথে কাস্টম কনস্ট্রাক্টর রয়েছে এমন কোনও বস্তুর সাথে এই সমাধানটি কাজ করার জন্য আমাকে সঠিক দিকে নির্দেশ করতে পারে।
মার্কো

আমি এগিয়ে গিয়ে একটি ফাংশন এ এটি নির্মিত। মনে রাখবেন এটি এখনও সাবক্লাসের সাথে কাজ করে না। gist.github.com/sixpeteunder/2bec86208775f131ce686d42f18d8621
পিটার লেঞ্জো

17

আপনি জেহানস স্মিটের সিরিয়ালাইজার লাইব্রেরি ব্যবহার করতে পারেন ।

$serializer = JMS\Serializer\SerializerBuilder::create()->build();
$object = $serializer->deserialize($jsonData, 'MyNamespace\MyObject', 'json');

জেএমএস সিরিয়ালাইজের সর্বশেষ সংস্করণে বাক্য গঠনটি হ'ল:

$serializer = SerializerBuilder::create()->build();
$object = $serializer->deserialize($jsonData, MyObject::class, 'json');

4
সিনট্যাক্সটি জেএমএস সিরিয়ালাইজার সংস্করণের উপর নির্ভরশীল নয়, বরং পিএইচপি সংস্করণে - পিএইচপি 5.5 থেকে শুরু করে আপনি ::classস্বরলিপিটি ব্যবহার করতে পারেন : php.net/manual/en/…
ইভান ইয়ারিচ

4

আপনি নিজের অবজেক্টের জন্য একটি মোড়ক তৈরি করতে পারেন এবং মোড়ককে এটির মতো করে তুলতে পারেন। এবং এটি মাল্টিলেভাল অবজেক্টের সাথে কাজ করবে।

<?php
class Obj
{
    public $slave;

    public function __get($key) {
        return property_exists ( $this->slave ,  $key ) ? $this->slave->{$key} : null;
    }

    public function __construct(stdClass $slave)
    {
        $this->slave = $slave;
    }
}

$std = json_decode('{"s3":{"s2":{"s1":777}}}');

$o = new Obj($std);

echo $o->s3->s2->s1; // you will have 777

3

না, পিএইচপি 5.5.1 হিসাবে এটি সম্ভব নয়।

কেবলমাত্র json_decodeস্ট্যান্ডক্লাস অবজেক্টের পরিবর্তে রিটার্ন সহযোগী অ্যারেগুলি পাওয়া সম্ভব ।


3

আপনি নীচের উপায়ে এটি করতে পারেন ..

<?php
class CatalogProduct
{
    public $product_id;
    public $sku;
    public $name;
    public $set;
    public $type;
    public $category_ids;
    public $website_ids;

    function __construct(array $data) 
    {
        foreach($data as $key => $val)
        {
            if(property_exists(__CLASS__,$key))
            {
                $this->$key =  $val;
            }
        }
    }
}

?>

আরও তথ্যের জন্য জেসন-বা-অ্যারে থেকে কাস্টম-ক্লাস-ইন-পিএইচপি-থেকে-তৈরি দেখুন


3

আমি অবাক হয়েছি এখনও কেউ এর উল্লেখ করেনি।

সিমফনি সিরিয়ালাইজার উপাদানটি ব্যবহার করুন: https://symfony.com/doc/current/components/serializer.html

অবজেক্ট থেকে জেএসএন-তে সিরিয়ালিং:

use App\Model\Person;

$person = new Person();
$person->setName('foo');
$person->setAge(99);
$person->setSportsperson(false);

$jsonContent = $serializer->serialize($person, 'json');

// $jsonContent contains {"name":"foo","age":99,"sportsperson":false,"createdAt":null}

echo $jsonContent; // or return it in a Response

জেএসওএন থেকে অবজেক্টে ডিসিরিয়াইজিং: (এই উদাহরণটি কেবলমাত্র বিন্যাসগুলির নমনীয়তা প্রদর্শনের জন্য এক্সএমএল ব্যবহার করে)

use App\Model\Person;

$data = <<<EOF
<person>
    <name>foo</name>
    <age>99</age>
    <sportsperson>false</sportsperson>
</person>
EOF;

$person = $serializer->deserialize($data, Person::class, 'xml');

2

প্রতিবিম্ব ব্যবহার :

function json_decode_object(string $json, string $class)
{
    $reflection = new ReflectionClass($class);
    $instance = $reflection->newInstanceWithoutConstructor();
    $json = json_decode($json, true);
    $properties = $reflection->getProperties();
    foreach ($properties as $key => $property) {
        $property->setAccessible(true);
        $property->setValue($instance, $json[$property->getName()]);
    }
    return $instance;
}

1

গর্ডন যেমন বলেছেন তেমন সম্ভব নয়। তবে আপনি যদি কোনও স্ট্রিং পাওয়ার উপায় খুঁজছেন যা একটি গিভ ক্লাসের উদাহরণ হিসাবে ডিকোড করা যায় তবে আপনি এর পরিবর্তে সিরিয়ালাইজ এবং আনসিরিয়ালাইজ করতে পারেন ।

class Foo
{

    protected $bar = 'Hello World';

    function getBar() {
        return $this->bar;
    }

}

$string = serialize(new Foo);

$foo = unserialize($string);
echo $foo->getBar();

এটি প্রশ্নের সমাধান বলে মনে হচ্ছে না। যদি এটি হয় তবে আপনাকে কিছু ব্যাখ্যা সরবরাহ করতে হবে।
ফেলিক্স ক্লিং

1

আমি একবার এই উদ্দেশ্যে একটি বিমূর্ত বেস শ্রেণি তৈরি করেছি। আসুন এটিকে JsonConvertible বলি। এটি জনসাধারণের সদস্যকে সিরিয়ালাইজ এবং deserialize করা উচিত। প্রতিবিম্ব এবং দেরী স্ট্যাটিক বাঁধাই ব্যবহার করে এটি সম্ভব।

abstract class JsonConvertible {
   static function fromJson($json) {
       $result = new static();
       $objJson = json_decode($json);
       $class = new \ReflectionClass($result);
       $publicProps = $class->getProperties(\ReflectionProperty::IS_PUBLIC);
       foreach ($publicProps as $prop) {
            $propName = $prop->name;
            if (isset($objJson->$propName) {
                $prop->setValue($result, $objJson->$propName);
            }
            else {
                $prop->setValue($result, null);
            }
       }
       return $result;
   }
   function toJson() {
      return json_encode($this);
   }
} 

class MyClass extends JsonConvertible {
   public $name;
   public $whatever;
}
$mine = MyClass::fromJson('{"name": "My Name", "whatever": "Whatever"}');
echo $mine->toJson();

কেবল স্মৃতি থেকে তাই সম্ভবত নির্দোষ নয়। আপনাকে স্ট্যাটিক বৈশিষ্ট্যগুলিও বাদ দিতে হবে এবং জেসন থেকে / থেকে সিরিয়ালযুক্ত হওয়ার সময় উত্পন্ন শ্রেণিগুলিকে কিছু সম্পত্তি উপেক্ষা করার সুযোগ দিতে পারে। আমি আশা করি আপনি যাইহোক, ধারণা পাবেন।


0

জেএসএন হ'ল বিভিন্ন প্রোগ্রামিং ভাষার (এবং এটি জাভাস্ক্রিপ্টের একটি উপসেট) মধ্যে ডেটা স্থানান্তর করার জন্য একটি সহজ প্রোটোকল যা কেবলমাত্র নির্দিষ্ট ধরণের সমর্থন করে: সংখ্যা, স্ট্রিং, অ্যারে / তালিকা, অবজেক্ট / ডিক্টস d অবজেক্টগুলি কেবল কী = মানচিত্রের মানচিত্র এবং অ্যারে তালিকাভুক্ত তালিকা দেওয়া হয়।

সুতরাং কাস্টম অবজেক্টগুলি জেনেরিক উপায়ে প্রকাশ করার কোনও উপায় নেই। সমাধানটি এমন একটি কাঠামো সংজ্ঞায়িত করছে যেখানে আপনার প্রোগ্রামগুলি গুলি জানবে যে এটি কোনও কাস্টম অবজেক্ট।

এখানে একটি উদাহরণ:

{ "cls": "MyClass", fields: { "a": 123, "foo": "bar" } }

এই একটি দৃষ্টান্ত তৈরি করতে ব্যবহার করা যেতে পারে MyClassএবং ক্ষেত্র নির্ধারণ করে aএবং fooকরতে 123এবং "bar"


6
এটি সত্য হতে পারে, তবে প্রশ্নটি জেনেরিক উপায়ে অবজেক্টগুলি উপস্থাপন করার বিষয়ে জিজ্ঞাসা করছে না। মনে হচ্ছে তিনি একটি নির্দিষ্ট জেএসওন ব্যাগ পেয়েছেন যা একটি বা উভয় প্রান্তে নির্দিষ্ট শ্রেণিতে মানচিত্র করে। আপনি জেনসনকে নন-জেনেরিক নামের ক্লাসগুলির সুস্পষ্ট ক্রমিক হিসাবে এইভাবে ব্যবহার করতে পারবেন না এমন কোনও কারণ নেই। আপনি যদি জেনেরিক সমাধান চান তবে এটির নামকরণ ঠিক আছে, তবে জেএসওএন কাঠামোর সাথে চুক্তিতে সম্মত হওয়ার ক্ষেত্রেও কিছু ভুল নেই।
ডগডাব্লু

আপনি এনকোডিং শেষে সিরিয়ালাইজেবল প্রয়োগ করে এবং ডিকোডিংয়ের শেষে শর্তযুক্ত রাখলে এটি কাজ করতে পারে। এমনকি সঠিকভাবে সংগঠিত হলে সাবক্লাসের সাথেও কাজ করতে পারে।
পিটার লেঞ্জো

0

আমি এগিয়ে গিয়ে জন পিতিটের উত্তরটি একটি ফাংশন ( সংক্ষেপে ) হিসাবে প্রয়োগ করেছি :

function json_decode_to(string $json, string $class = stdClass::class, int $depth = 512, int $options = 0)
{
    $stdObj = json_decode($json, false, $depth, $options);
    if ($class === stdClass::class) return $stdObj;

    $count = strlen($class);
    $temp = serialize($stdObj);
    $temp = preg_replace("@^O:8:\"stdClass\":@", "O:$count:\"$class\":", $temp);
    return unserialize($temp);  
}

এটি আমার ব্যবহারের ক্ষেত্রে পুরোপুরি কাজ করেছে। তবে ইয়েভেগেনি আফানাস্যিয়েভের প্রতিক্রিয়া আমার কাছে সমান প্রতিশ্রুতিবদ্ধ বলে মনে হচ্ছে। আপনার ক্লাসে একটি অতিরিক্ত "কন্সট্রাক্টর" রাখা সম্ভব হতে পারে:

public static function withJson(string $json) {
    $instance = new static();
    // Do your thing
    return $instance;
}

এটি এই উত্তর দ্বারা অনুপ্রাণিত ।

সম্পাদনা: আমি বেশ কিছুদিন ধরে কররিয়েট / জসন-ডিকোডার ব্যবহার করছি এবং এটি নিয়ে আমার কোনও অসুবিধা হয়নি। এটি হালকা ও খুব সহজেই এক্সটেনসিবল। এখানে একটি বাঁধাইয়ের একটি উদাহরণ যা আমি লিখেছিলাম JSON কে কার্বন / কার্বন মিমিটেবল অবজেক্টে ডিজিজায়াল করতে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.