首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >使用强制转换将JSON反序列化到PHP?

使用强制转换将JSON反序列化到PHP?
EN

Stack Overflow用户
提问于 2009-03-18 14:25:29
回答 11查看 25.8K关注 0票数 28

假设我有一个具有'name‘和'password’属性的User类,以及一个'save‘方法。当通过json_encode将这个类的对象序列化为JSON时,方法被正确地跳过,我以类似{'name':'testName','password':'testPassword'}结束。

然而,当通过json_decode进行反序列化时,我最终得到了一个保存对象,而不是用户对象,这是有意义的,但这意味着该对象缺少“StdClass”方法。有没有办法将结果对象转换为用户,或者向json_decode提供一些关于我期望的对象类型的提示?

EN

回答 11

Stack Overflow用户

发布于 2015-09-17 22:29:55

这是个老问题,但也许有人会发现这很有用。

我已经创建了一个带有静态函数的抽象类,您可以在对象上继承这些函数,以便将任何JSON反序列化为继承类实例。

代码语言:javascript
复制
abstract class JsonDeserializer
{
    /**
     * @param string|array $json
     * @return $this
     */
    public static function Deserialize($json)
    {
        $className = get_called_class();
        $classInstance = new $className();
        if (is_string($json))
            $json = json_decode($json);

        foreach ($json as $key => $value) {
            if (!property_exists($classInstance, $key)) continue;

            $classInstance->{$key} = $value;
        }

        return $classInstance;
    }
    /**
     * @param string $json
     * @return $this[]
     */
    public static function DeserializeArray($json)
    {
        $json = json_decode($json);
        $items = [];
        foreach ($json as $item)
            $items[] = self::Deserialize($item);
        return $items;
    }
}

您可以通过在具有JSON将具有的值的类上继承它来使用它:

代码语言:javascript
复制
class MyObject extends JsonDeserializer
{
    /** @var string */
    public $property1;

    /** @var string */
    public $property2;

    /** @var string */
    public $property3;

    /** @var array */
    public $array1;
}

示例用法:

代码语言:javascript
复制
$objectInstance = new MyObject();
$objectInstance->property1 = 'Value 1';
$objectInstance->property2 = 'Value 2';
$objectInstance->property3 = 'Value 3';
$objectInstance->array1 = ['Key 1' => 'Value 1', 'Key 2' => 'Value 2'];

$jsonSerialized = json_encode($objectInstance);

$deserializedInstance = MyObject::Deserialize($jsonSerialized);

如果JSON包含目标对象的数组,则可以使用::DeserializeArray方法。

Here是一个可运行的示例。

票数 22
EN

Stack Overflow用户

发布于 2009-03-18 14:31:46

我认为处理这个问题的最好方法是通过构造函数,无论是直接还是通过工厂:

代码语言:javascript
复制
class User
{
   public $username;
   public $nestedObj; //another class that has a constructor for handling json
   ...

   // This could be make private if the factories below are used exclusively
   // and then make more sane constructors like:
   //     __construct($username, $password)
   public function __construct($mixed)
   {
       if (is_object($mixed)) {
           if (isset($mixed->username))
               $this->username = $mixed->username;
           if (isset($mixed->nestedObj) && is_object($mixed->nestedObj))
               $this->nestedObj = new NestedObject($mixed->nestedObj);
           ...
       } else if (is_array($mixed)) {
           if (isset($mixed['username']))
               $this->username = $mixed['username'];
           if (isset($mixed['nestedObj']) && is_array($mixed['nestedObj']))
               $this->nestedObj = new NestedObj($mixed['nestedObj']);
           ...
       }
   }
   ...

   public static fromJSON_by_obj($json)
   {
       return new self(json_decode($json));
   }

   public static fromJSON_by_ary($json)
   {
       return new self(json_decode($json, TRUE)); 
   }
}
票数 9
EN

Stack Overflow用户

发布于 2009-03-18 15:06:13

简短的回答:没有(据我所知*)

长答案: json_encode将只序列化公共变量。正如您在JSON spec中看到的那样,没有“函数”数据类型。这就是为什么您的方法没有序列化为JSON对象的两个原因。

Ryan Graham是对的-将这些对象重新创建为非stdClass实例的唯一方法是在反序列化后重新创建它们。

示例

代码语言:javascript
复制
<?php

class Person
{
    public $firstName;
    public $lastName;

    public function __construct( $firstName, $lastName )
    {
        $this->firstName = $firstName;
        $this->lastName = $lastName;
    }

    public static function createFromJson( $jsonString )
    {
        $object = json_decode( $jsonString );
        return new self( $object->firstName, $object->lastName );
    }

    public function getName()
    {
        return $this->firstName . ' ' . $this->lastName;
    }
}

$p = new Person( 'Peter', 'Bailey' );
$jsonPerson = json_encode( $p );

$reconstructedPerson = Person::createFromJson( $jsonPerson );

echo $reconstructedPerson->getName();

或者,除非您确实需要JSON形式的数据,否则您可以只使用normal serialization并利用__sleep() and __wakeup() hooks来实现额外的定制。

*a previous question of my own中,有人建议您可以实现一些SPL接口来定制json_encode()的输入/输出,但我的测试显示这些都是徒劳的。

票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/658469

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档