假设我有一个具有'name‘和'password’属性的User类,以及一个'save‘方法。当通过json_encode将这个类的对象序列化为JSON时,方法被正确地跳过,我以类似{'name':'testName','password':'testPassword'}结束。
然而,当通过json_decode进行反序列化时,我最终得到了一个保存对象,而不是用户对象,这是有意义的,但这意味着该对象缺少“StdClass”方法。有没有办法将结果对象转换为用户,或者向json_decode提供一些关于我期望的对象类型的提示?
发布于 2015-09-17 22:29:55
这是个老问题,但也许有人会发现这很有用。
我已经创建了一个带有静态函数的抽象类,您可以在对象上继承这些函数,以便将任何JSON反序列化为继承类实例。
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将具有的值的类上继承它来使用它:
class MyObject extends JsonDeserializer
{
/** @var string */
public $property1;
/** @var string */
public $property2;
/** @var string */
public $property3;
/** @var array */
public $array1;
}
示例用法:
$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是一个可运行的示例。
发布于 2009-03-18 14:31:46
我认为处理这个问题的最好方法是通过构造函数,无论是直接还是通过工厂:
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));
}
}
发布于 2009-03-18 15:06:13
简短的回答:没有(据我所知*)
长答案: json_encode将只序列化公共变量。正如您在JSON spec中看到的那样,没有“函数”数据类型。这就是为什么您的方法没有序列化为JSON对象的两个原因。
Ryan Graham是对的-将这些对象重新创建为非stdClass实例的唯一方法是在反序列化后重新创建它们。
示例
<?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()的输入/输出,但我的测试显示这些都是徒劳的。
https://stackoverflow.com/questions/658469
复制相似问题