क्या stdClass के अलावा किसी ऑब्जेक्ट के लिए json स्ट्रिंग को डिकोड करना संभव है?
क्या stdClass के अलावा किसी ऑब्जेक्ट के लिए json स्ट्रिंग को डिकोड करना संभव है?
जवाबों:
अपने आप नहीं। लेकिन आप इसे पुराने जमाने का मार्ग मान सकते हैं।
$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);
हमने JsonMapper का निर्माण किया को JSON ऑब्जेक्ट्स को अपने मॉडल कक्षाओं में स्वचालित रूप से मैप करने के लिए । यह नेस्टेड / चाइल्ड ऑब्जेक्ट्स के साथ ठीक काम करता है।
यह केवल मानचित्रण के लिए डॉकब्लॉक प्रकार की जानकारी पर निर्भर करता है, जो कि अधिकांश वर्ग गुणों का वैसे भी है:
<?php
$mapper = new JsonMapper();
$contactObject = $mapper->map(
json_decode(file_get_contents('http://example.org/contact.json')),
new Contact()
);
?>
आप इसे कर सकते हैं - यह एक कीचड़ है लेकिन पूरी तरह से संभव है। हमें तब करना पड़ा जब हमने काउचबेस में चीजों को स्टोर करना शुरू किया।
$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
हमारे बेंचमार्क में यह तेजी से सभी वर्ग चर के माध्यम से पुनरावृति करने की कोशिश कर रहा था।
कैविएट: stdClass के अलावा नेस्टेड ऑब्जेक्ट्स के लिए काम नहीं करेगा
संपादित करें: डेटा स्रोत को ध्यान में रखें, यह दृढ़ता से अनुशंसा की जाती है कि आप जोखिमों के बहुत ही कुशल विश्लेषण के बिना उपयोगकर्ताओं से यह अविश्वसनीय डेटा प्रदान नहीं करते हैं।
{ "a": {"b":"c"} }, जहां वस्तु aएक अन्य वर्ग की है और न केवल एक सहयोगी सरणी है?
आप J ohannes Schmitt के Serializer लाइब्रेरी का उपयोग कर सकते हैं ।
$serializer = JMS\Serializer\SerializerBuilder::create()->build();
$object = $serializer->deserialize($jsonData, 'MyNamespace\MyObject', 'json');
जेएमएस धारावाहिक के नवीनतम संस्करण में वाक्य रचना है:
$serializer = SerializerBuilder::create()->build();
$object = $serializer->deserialize($jsonData, MyObject::class, 'json');
::classसंकेतन का उपयोग कर सकते हैं : php.net/manual/en/…
आप अपनी वस्तु के लिए एक आवरण बना सकते हैं और आवरण को ऐसा बना सकते हैं जैसे वह वस्तु है। और यह बहुस्तरीय वस्तुओं के साथ काम करेगा।
<?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
नहीं, यह PHP 5.5.1 के रूप में संभव नहीं है।
json_decodeStdClass ऑब्जेक्ट्स के बजाय वापसी सहयोगी सरणियों के लिए केवल एक ही चीज़ संभव है ।
आप इसे नीचे तरीके से कर सकते हैं।
<?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;
}
}
}
}
?>
अधिक जानकारी के लिए create-custom-in-php-from-json-or-array देखें
मुझे आश्चर्य है कि किसी ने भी इसका उल्लेख नहीं किया, फिर भी।
Symfony Serializer घटक का उपयोग करें: https://symfony.com/doc/current/compords/serializer.html
वस्तु से JSON तक सीरियल:
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
JSON से ऑब्जेक्ट के लिए Deserializing: (यह उदाहरण केवल स्वरूपों के लचीलेपन को प्रदर्शित करने के लिए XML का उपयोग करता है)
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');
प्रतिबिंब का उपयोग करें :
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;
}
जैसा कि गॉर्डन कहते हैं कि यह संभव नहीं है। लेकिन अगर आप एक स्ट्रिंग प्राप्त करने का एक तरीका ढूंढ रहे हैं जो कि किसी दिए गए वर्ग के उदाहरण के रूप में डिकोड किया जा सकता है, तो आप इसके बजाय क्रमबद्ध और अचयनित उपयोग कर सकते हैं ।
class Foo
{
protected $bar = 'Hello World';
function getBar() {
return $this->bar;
}
}
$string = serialize(new Foo);
$foo = unserialize($string);
echo $foo->getBar();
मैंने एक बार इस उद्देश्य के लिए एक सार आधार वर्ग बनाया था। चलो इसे JsonConvertible कहते हैं। इसे जनता के सदस्यों को क्रमबद्ध करना चाहिए और उन्हें हताश करना चाहिए। यह प्रतिबिंब और देर से स्थिर बंधन का उपयोग करके संभव है।
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();
बस स्मृति से, इसलिए शायद निर्दोष नहीं। आपको स्थैतिक गुणों को भी बाहर करना होगा और व्युत्पन्न वर्गों को कुछ गुणों को अनदेखा करने का मौका दे सकता है जब धारावाहिक में / से जस की तस। मुझे आशा है कि आपको यह विचार मिलेगा, फिर भी।
JSON विभिन्न प्रोग्रामिंग भाषाओं (और यह जावास्क्रिप्ट का एक सबसेट भी है) के बीच डेटा स्थानांतरित करने के लिए एक सरल प्रोटोकॉल है जो केवल कुछ प्रकारों का समर्थन करता है: नंबर, स्ट्रिंग्स, सरणियाँ / सूचियाँ, ऑब्जेक्ट्स / डाइक। ऑब्जेक्ट्स केवल कुंजी = मूल्य मानचित्र हैं और Arrays सूचियों का आदेश दिया गया है।
तो सामान्य तरीके से कस्टम ऑब्जेक्ट्स को व्यक्त करने का कोई तरीका नहीं है। समाधान एक संरचना को परिभाषित कर रहा है जहां आपके कार्यक्रम को पता चलेगा कि यह एक कस्टम वस्तु है।
यहाँ एक उदाहरण है:
{ "cls": "MyClass", fields: { "a": 123, "foo": "bar" } }
इस का एक उदाहरण बनाने के लिए इस्तेमाल किया जा सकता है MyClassऔर खेतों सेट aऔर fooकरने के लिए 123और "bar"।
मैंने आगे बढ़कर जॉन पेटिट के जवाब को एक फ़ंक्शन ( जिस्ट ) के रूप में लागू किया :
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;
}
यह भी इस उत्तर से प्रेरित है ।