Можно ли декодировать строку json для объекта, отличного от stdClass?
Json_decode для пользовательского класса
Ответ 1
Не автоматически. Но вы можете сделать это старомодный маршрут.
$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 the sweetness.
$class = new JSONObject($jsonString);
print_r($class);
Ответ 2
Вы можете сделать это - это клумба, но вполне возможно. Мы должны были сделать, когда мы начали хранить вещи в диване.
$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
Изменение: имейте в виду источник данных, настоятельно рекомендуется, чтобы вы не делали этого с ненадежными данными от пользователей без тщательного анализа рисков.
Ответ 3
Мы построили JsonMapper, чтобы автоматически сопоставлять объекты JSON на наших собственных классах моделей. Он отлично работает с вложенными/дочерними объектами.
Он использует только информацию типа типа docblock для сопоставления, которая имеет большинство свойств класса:
<?php
$mapper = new JsonMapper();
$contactObject = $mapper->map(
json_decode(file_get_contents('http://example.org/contact.json')),
new Contact()
);
?>
Ответ 4
Вы можете использовать библиотеку J ohannes Schmitt Serializer.
$serializer = JMS\Serializer\SerializerBuilder::create()->build();
$object = $serializer->deserialize($jsonData, 'MyNamespace\MyObject', 'json');
В последней версии сериализатора JMS синтаксис:
$serializer = SerializerBuilder::create()->build();
$object = $serializer->deserialize($jsonData, MyObject::class, 'json');
Ответ 5
Нет, это невозможно с PHP 5.5.1.
Единственное возможное - json_decode
возвращать ассоциированные массивы вместо объектов StdClass.
Ответ 6
Вы можете создать оболочку для своего объекта и сделать оболочку похожим на сам объект. И он будет работать с многоуровневыми объектами.
<?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
Ответ 7
Вы можете сделать это ниже.
<?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;
}
}
}
}
? >
Ответ 8
Как говорит Гордон, это невозможно. Но если вы ищете способ получить строку, которая может быть расшифрована как экземпляр класса, вы можете использовать serialize и unserialize вместо этого.
class Foo
{
protected $bar = 'Hello World';
function getBar() {
return $this->bar;
}
}
$string = serialize(new Foo);
$foo = unserialize($string);
echo $foo->getBar();
Ответ 9
Я однажды создал для этой цели базовый базовый класс. Позвольте называть его 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. Надеюсь, вы получите эту идею, тем не менее.
Ответ 10
Я думаю, что самый простой способ:
function mapJSON($json, $class){
$decoded_object = json_decode($json);
foreach ($decoded_object as $key => $value) {
$class->$key = $value;
}
return $class;}
Ответ 11
JSON - простой протокол для передачи данных между различными языками программирования (а также подмножеством JavaScript), который поддерживает только определенные типы: числа, строки, массивы/списки, объекты /dicts. Объекты - это только ключи = значения, а массивы - упорядоченные списки.
Таким образом, нет возможности выразить пользовательские объекты в общем виде. Решение определяет структуру, в которой ваша программа будет знать, что это пользовательский объект.
Вот пример:
{ "cls": "MyClass", fields: { "a": 123, "foo": "bar" } }
Это можно использовать для создания экземпляра MyClass
и установки полей a
и foo
на 123
и "bar"
.