Можно ли декодировать строку json для объекта, отличного от stdClass?
Не автоматически. Но вы можете сделать это старомодным путем.
$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);
Вы можете это сделать – это kludge, но вполне возможно. Мы должны были делать, когда мы начали хранить вещи в couchbase.
$stdobj = json_decode($json_encoded_myClassInstance); //JSON to stdClass $temp = serialize($stdobj); //stdClass to serialized
// Теперь мы достигаем и меняем класс сериализованного объекта
$temp = preg_replace('@^O:8:"stdClass":@','O:7:"MyClass":',$temp);
// Unserialize и уйти, как ничего не случилось
$myClassInstance = unserialize($temp); // Presto a php Class
В наших тестах это было намного быстрее, чем пытаться перебирать все переменные класса.
Caveat: не будет работать для вложенных объектов, кроме stdClass
Изменить: имейте в виду источник данных, настоятельно рекомендуется, чтобы вы не делали этого с недоверенными данными от пользователей без очень тщательного анализа рисков.
Мы создали JsonMapper для автоматического отображения объектов JSON на наши собственные классы моделей. Он отлично работает с вложенными / дочерними объектами.
Он используется только для информации типа docblock для сопоставления, которая в любом случае имеет большинство свойств класса:
<?php $mapper = new JsonMapper(); $contactObject = $mapper->map( json_decode(file_get_contents('http://example.org/contact.json')), new Contact() ); ?>
Вы можете использовать библиотеку Serializer J ohannes Schmitt .
$serializer = JMS\Serializer\SerializerBuilder::create()->build(); $object = $serializer->deserialize($jsonData, 'MyNamespace\MyObject', 'json');
Нет, это невозможно с PHP 5.5.1.
Единственное, что возможно, – это вернуть json_decode
ассоциированные массивы вместо объектов StdClass.
Как говорит Гордон, это невозможно. Но если вы ищете способ получить строку, которая может быть расшифрована как экземпляр класса give, вы можете вместо этого использовать сериализацию и unserialize.
class Foo { protected $bar = 'Hello World'; function getBar() { return $this->bar; } } $string = serialize(new Foo); $foo = unserialize($string); echo $foo->getBar();
Для этого я создал абстрактный базовый класс. Назовем это JsonConvertible. Он должен сериализовать и десериализовать публичных членов. Это возможно, используя Reflection и позднюю статическую привязку.
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. Надеюсь, вы получите эту идею, тем не менее.
Вы можете сделать это ниже.
<?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-class-in-php-from-json-or-array
Вы можете создать оболочку для своего объекта и сделать оболочку похожим на сам объект. И он будет работать с многоуровневыми объектами.
<?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
JSON – это простой протокол для передачи данных между различными языками программирования (а также подмножество JavaScript), который поддерживает только определенные типы: числа, строки, массивы / списки, объекты / dicts. Объекты – это только ключи = значения, а массивы – упорядоченные списки.
Таким образом, нет возможности выразить пользовательские объекты в общем виде. Решение определяет структуру, в которой ваша программа (ы) будет знать, что это настраиваемый объект.
Вот пример:
{ "cls": "MyClass", fields: { "a": 123, "foo": "bar" } }
Это можно использовать для создания экземпляра MyClass
и установки полей a
и foo
на 123
и "bar"
.