我今天碰到了这个问题.来自PHP.net doc:serialize
注意: Object的私有成员的类名前置于成员名称; 受保护的成员在成员名称前面加上'*'.这些前置值在任一侧都有空字节.
我正在使用debug_backtrace为调试报告生成跟踪,该报告得到json_encoded.在内部,它使用序列化器生成跟踪数据.
这是:(部分)输出json_encode:
{"\u0000MyObject\u0000my_var":[]}
Run Code Online (Sandbox Code Playgroud)
问题是json_decode无法处理这个问题,它会抱怨null字节.
很json_encode高兴写出json_decode无法解码的空字节.这对我来说似乎有点不稳定.我希望能够json_encode处理必要的转义,或者至少json_decode可以解析由json_encode它产生的任何东西,但事实并非如此.
我想我有几个解决方案:
json_encode以便它不会产生空字节json_decode,使其接受空字节有没有人遇到这个问题,你是如何解决它的?
样品:
<?php
class MyClass {
public $mypublic = 1;
private $myprivate = 2;
public function myfunc() {
return debug_backtrace();
}
}
$c = new MyClass();
$json = json_encode(call_user_func_array(array($c, "myfunc"), new MyClass()));
echo $json;
echo json_decode($json); // <-- Fatal error: Cannot access property started with '\0' in test.php on line 12
Run Code Online (Sandbox Code Playgroud)
解
因为
call_user_func_array当第二个参数call_user_func_array不是数组时,PHP 5.3 会抛出警告.在那之前你必须自己检查一下.
(对不起,这可能会更好地作为评论,因为它没有完全回答你的问题 - 但它有点太长了)
我尝试用PHP 5.3和5.2来复制你描述的内容,这就是我得到的内容:
首先,让我们创建一个具有私有属性的类并实现它:
class A {
public $pub = 10;
private $priv = 20;
}
$a = new A();
var_dump($a);
Run Code Online (Sandbox Code Playgroud)
哪个让我:
object(A)[1]
public 'pub' => int 10
private 'priv' => int 20
Run Code Online (Sandbox Code Playgroud)
现在,如果我是serialize()我的对象:
$serialized = serialize($a);
var_dump($serialized);
Run Code Online (Sandbox Code Playgroud)
我明白了:
string 'O:1:"A":2:{s:3:"pub";i:10;s:7:"?A?priv";i:20;}' (length=46)
Run Code Online (Sandbox Code Playgroud)
这几乎就是你描述的内容:-property的名字null周围有那些字节private.
让我们继续json_encode():
$jsoned = json_encode($serialized);
var_dump($jsoned);
Run Code Online (Sandbox Code Playgroud)
就像你说的那样,这给了我一些字符串\u0000:
string '"O:1:\"A\":2:{s:3:\"pub\";i:10;s:7:\"\u0000A\u0000priv\";i:20;}"' (length=64)
Run Code Online (Sandbox Code Playgroud)
现在,如果我尝试json_decode()这个字符串:
$unjsoned = json_decode($jsoned);
var_dump($unjsoned);
Run Code Online (Sandbox Code Playgroud)
这是我得到的:
string 'O:1:"A":2:{s:3:"pub";i:10;s:7:"?A?priv";i:20;}' (length=46)
Run Code Online (Sandbox Code Playgroud)
=>空字节似乎没有丢失:它们是从JSON字符串中正确地重新创建的.
并呼吁unserialize():
$unserialized = unserialize($unjsoned);
var_dump($unserialized);
Run Code Online (Sandbox Code Playgroud)
我找回了我的初始对象:
object(A)[2]
public 'pub' => int 10
private 'priv' => int 20
Run Code Online (Sandbox Code Playgroud)
因此,在序列化+编码和解码+反序列化时,我似乎没有重现您的问题...
我应该补充一点,我无法在这两个方面找到任何关于这种错误的信息:
现在,如果我尝试使用更复杂的对象,使用包含私有成员的类,该成员本身就是一个包含私有属性的对象:
class A {
private $priv;
public function __construct() {
$this->priv = new B();
}
}
class B {
private $b = 10;
}
Run Code Online (Sandbox Code Playgroud)
我得到完全相同的行为:一切正常 - 这是我得到的输出,当使用var_dump()与以前完全相同的动作和调用时:
object(A)[1]
private 'priv' =>
object(B)[2]
private 'b' => int 10
string 'O:1:"A":1:{s:7:"?A?priv";O:1:"B":1:{s:4:"?B?b";i:10;}}' (length=54)
string '"O:1:\"A\":1:{s:7:\"\u0000A\u0000priv\";O:1:\"B\":1:{s:4:\"\u0000B\u0000b\";i:10;}}"' (length=84)
string 'O:1:"A":1:{s:7:"?A?priv";O:1:"B":1:{s:4:"?B?b";i:10;}}' (length=54)
object(A)[3]
private 'priv' =>
object(B)[4]
private 'b' => int 10
Run Code Online (Sandbox Code Playgroud)
在这里,我无法重现你描述的问题.
如果我试试这个:
var_dump(
unserialize(
json_decode('{"\u0000MyObject\u0000my_var":[]}')
)
);
Run Code Online (Sandbox Code Playgroud)
我确实遇到了麻烦:
Fatal error: Cannot access property started with '\0'
Run Code Online (Sandbox Code Playgroud)
但是,考虑一下,如果我尝试解码它"我自己",我真的不知道你是如何获得这样的JSON字符串的......
你确定其他地方没有问题吗?喜欢在编码过程中?