Jer*_*lft 19 php serialization json
假设我有一个带有'name'和'password'属性的User类,以及一个'save'方法.当通过json_encode将此类的对象序列化为JSON时,该方法被正确跳过,我最终得到类似{'name':'testName','password':'testPassword'}的内容.
但是,当通过json_decode反序列化时,我最终得到一个StdClass对象而不是User对象,这是有道理的,但这意味着该对象缺少"保存"方法.有没有办法将结果对象作为用户进行转换,或者为json_decode提供一些关于我期望的对象类型的提示?
Ren*_*ers 16
老问题,但也许有人会觉得这很有用.
我已经创建了一个带有静态函数的抽象类,您可以在对象上继承这些函数,以便将任何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;
}
}
Run Code Online (Sandbox Code Playgroud)
您可以通过在具有JSON将具有的值的类上继承它来使用它:
class MyObject extends JsonDeserializer
{
/** @var string */
public $property1;
/** @var string */
public $property2;
/** @var string */
public $property3;
/** @var array */
public $array1;
}
Run Code Online (Sandbox Code Playgroud)
用法示例:
$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);
Run Code Online (Sandbox Code Playgroud)
::DeserializeArray如果您的JSON包含目标对象的数组,则可以使用该方法.
这是一个可运行的样本.
我认为处理这个的最好方法是通过构造函数,直接或通过工厂:
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));
}
}
Run Code Online (Sandbox Code Playgroud)
简答:不(不是我知道*)
答案很长:json_encode只会序列化公共变量.正如您在JSON规范中看到的那样,没有"函数"数据类型.这些都是您的方法未序列化到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();
Run Code Online (Sandbox Code Playgroud)
或者,除非您确实需要将数据作为JSON,否则您可以使用常规序列化并利用__sleep()和__wakeup()挂钩来实现其他自定义.
*在我之前的一个问题中,有人建议您可以实现一些SPL接口来自定义json_encode()的输入/输出,但我的测试显示那些是疯狂的追逐.
| 归档时间: |
|
| 查看次数: |
18229 次 |
| 最近记录: |