php json_decode 到自定义类

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5397758/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 21:16:10  来源:igfitidea点击:

json_decode to custom class

phpjson

提问by Tom

Is it possible to decode a json string to an object other than stdClass?

是否可以将 json 字符串解码为 stdClass 以外的对象?

回答by Michael McTiernan

Not automatically. But you can do it the old fashioned route.

不是自动的。但是你可以按照老式的路线来做。

$data = json_decode($json, true);

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

Or alternatively, you could make that more automatic:

或者,您可以使其更加自动化:

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

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

Edit: getting a little fancier:

编辑:变得有点狂热:

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);

回答by cweiske

We built JsonMapperto map JSON objects onto our own model classes automatically. It works fine with nested/child objects.

我们构建了JsonMapper来自动将 JSON 对象映射到我们自己的模型类上。它适用于嵌套/子对象。

It only relies on docblock type information for mapping, which most class properties have anyway:

它只依赖于 docblock 类型信息进行映射,大多数类属性无论如何都具有:

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

回答by John Pettitt

You can do it - it's a kludge but totally possible. We had to do when we started storing things in couchbase.

你可以做到——这是一个杂七杂八的事情,但完全有可能。当我们开始在沙发上存放东西时,我们不得不这样做。

$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 

In our benchmarks this was way faster than trying to iterate through all the class variables.

在我们的基准测试中,这比尝试遍历所有类变量要快得多。

Caveat: Won't work for nested objects other than stdClass

警告:不适用于 stdClass 以外的嵌套对象

Edit: keep in mind the data source, it's strongly recommended that you don't do this withe untrusted data from users without a very carful analysis of the risks.

编辑:请记住数据源,强烈建议您不要在没有对风险进行非常仔细分析的情况下使用来自用户的不受信任的数据来执行此操作。

回答by Malachi

You could use Johannes Schmitt's Serializer library.

你可以使用约翰内斯施密特的序列化程序库

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

In the latest version of the JMS serializer the syntax is:

在最新版本的 JMS 序列化程序中,语法是:

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

回答by Yevgeniy Afanasyev

You can make a wrapper for your object and make the wrapper look like it is the object itself. And it will work with multilevel objects.

您可以为您的对象制作一个包装器,并使包装器看起来就像是对象本身。它适用于多级对象。

<?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

回答by jigarshahindia

You can do it in below way ..

您可以通过以下方式做到这一点..

<?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;
            }
        }
    }
}

?>

?>

For more details visit create-custom-class-in-php-from-json-or-array

有关更多详细信息,请访问 create-custom-class-in-php-from-json-or-array

回答by Gordon

No, this is not possible as of PHP 5.5.1.

不,从 PHP 5.5.1 开始这是不可能的。

The only thing possible is to have json_decodereturn associate arrays instead of the StdClass objects.

唯一可能的是json_decode返回关联数组而不是 StdClass 对象。

回答by Francesco Terenzani

As Gordon says is not possible. But if you are looking for a way to obtain a string that can be decoded as an instance of a give class you can use serializeand unserialize instead.

正如戈登所说,这是不可能的。但是,如果您正在寻找一种方法来获取可以解码为给定类的实例的字符串,则可以改用序列化和反序列化。

class Foo
{

    protected $bar = 'Hello World';

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

}

$string = serialize(new Foo);

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

回答by klawipo

I once created an abstract base class for this purpose. Let's call it JsonConvertible. It should serialize and deserialize the public members. This is possible using Reflection and late static binding.

我曾经为此目的创建了一个抽象基类。我们称之为 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();

Just from memory, so probably not flawless. You will also have to exclude static properties and may give derived classes the chance to make some properties ignored when serialized to/from json. I hope you get the idea, nonetheless.

仅凭记忆,所以可能不是完美无缺的。您还必须排除静态属性,并且可能会给派生类机会在序列化到 json 时忽略某些属性。尽管如此,我希望你能明白。

回答by ThiefMaster

JSON is a simple protocol to transfer data between various programming languages (and it's also a subset of JavaScript) which supports just certain types: numbers, strings, arrays/lists, objects/dicts. Objects are just key=value maps and Arrays are ordered lists.

JSON 是一种在各种编程语言(它也是 JavaScript 的一个子集)之间传输数据的简单协议,它只支持某些类型:数字、字符串、数组/列表、对象/字典。对象只是键=值映射,数组是有序列表。

So there is no way to express custom objects in a generic way. The solution is defining a structure where your program(s) will know that it's a custom object.

所以没有办法以通用的方式表达自定义对象。解决方案是定义一个结构,让您的程序知道它是一个自定义对象。

Here's an example:

下面是一个例子:

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

This could be used to create an instance of MyClassand set the fields aand footo 123and "bar".

这可以用来创建实例MyClass,并设置领域afoo123"bar"