json_encode序列化空字节 [英] json_encode serialize null bytes

查看:78
本文介绍了json_encode序列化空字节的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了这个 serialize gotcha 今天.来自PHP.net doc:

I ran into this serialize gotcha today. From PHP.net doc:

注意: 对象的私有成员具有该成员的类名 姓名;受保护的成员的成员名称前带有"*".这些 前置值的两边均为空字节.

Note: Object's private members have the class name prepended to the member name; protected members have a '*' prepended to the member name. These prepended values have null bytes on either side.

我正在使用debug_backtrace生成调试报告的跟踪,该跟踪报告获取json_encode d.在内部,它使用序列化器生成跟踪数据.

I'm using debug_backtrace to generate a trace for a debug report, which gets json_encoded. Internally it uses the serializer to generate the data for the trace.

这是json_encode的(部分)输出:

{"\u0000MyObject\u0000my_var":[]}

问题是json_decode无法处理此问题,它将抱怨空字节.

The problem is that json_decode can't handle this, it will complain about the null bytes.

因此json_encode愉快地写入了json_decode无法解码的空字节.对我来说,这似乎有些不可思议.我希望json_encode处理必要的转义,或者至少json_decode可以解析json_encode产生的任何内容,但这似乎并非如此.

So json_encode happily writes the null bytes, that json_decode can't decode. This seems a little wonky to me. I would expect json_encode takes care of the necessary escaping, or at least that json_decode can parse anything produced by json_encode, but this doesn't seem to be the case.

我想我有几种解决方法:

I guess I have several solutions:

  • 从跟踪中剥离空字节,我对反序列化对象没有太大兴趣,我只想要一个字符串表示形式.
  • 将专用变量从跟踪中剥离出来.
  • 修复json_encode,使其不会产生空字节
  • 修复json_decode,使其接受空字节
  • Strip the null bytes from the trace, I'm not so much interested in unserializing the object, I just want a string representation.
  • Strip private variables all together from the trace.
  • Fix json_encode so that it doesn't produce null bytes
  • Fix json_decode so that it accepts null bytes

有人遇到这个问题了吗,您如何解决呢?

示例:

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


解决方案

因为PHP 5.3 call_user_func_array在第二次 call_user_func_array的参数不是数组.在那之前,您必须自己检查一下.

Since PHP 5.3 call_user_func_array will throw a warning when the second parameter of call_user_func_array is not an array. Until then you'll have to check it yourself.

推荐答案

(对不起,这可能不适合作为注释,因为它不能完全回答您的问题,但是对于它来说太长了那个)


我尝试用PHP 5.3和5.2再现您描述的内容,这就是我得到的:


I've tried reproducing what you describe, with both PHP 5.3 and 5.2, and here's what I get :

首先,让我们创建一个具有私有属性的类并实例化它:

First, let's create a class with a private property and instanciate it :

class A {
    public $pub = 10;
    private $priv = 20;
}

$a = new A();
var_dump($a);

哪个让我:

object(A)[1]
  public 'pub' => int 10
  private 'priv' => int 20


现在,如果我serialize()我的对象:


Now, if I serialize() my object :

$serialized = serialize($a);
var_dump($serialized);

我得到了:

string 'O:1:"A":2:{s:3:"pub";i:10;s:7:"�A�priv";i:20;}' (length=46)

您所描述的几乎是什么:private属性名称周围有那些null字节.

Which is pretty much what you describe : there are those null-bytes arround the private-property's name.


让我们继续json_encode():


And let's continue with json_encode() :

$jsoned = json_encode($serialized);
var_dump($jsoned);

正如您所说,这给了我一个带有一些\u0000的字符串:

Which gives me, like you said, a string with some \u0000 :

string '"O:1:\"A\":2:{s:3:\"pub\";i:10;s:7:\"\u0000A\u0000priv\";i:20;}"' (length=64)


现在,如果我尝试json_decode()此字符串:


Now, if I try to json_decode() this string :

$unjsoned = json_decode($jsoned);
var_dump($unjsoned);

这就是我得到的:

string 'O:1:"A":2:{s:3:"pub";i:10;s:7:"�A�priv";i:20;}' (length=46)

=>空字节似乎并没有丢失:它们是通过JSON字符串正确创建的.


然后,调用unserialize():


And, calling unserialize() on that :

$unserialized = unserialize($unjsoned);
var_dump($unserialized);

我拿回了我拥有的最初物体:

I get back the initial object I had :

object(A)[2]
  public 'pub' => int 10
  private 'priv' => int 20

所以,当进行序列化+编码和反编码+反序列化时,我似乎没有重现您的问题.

So, I don't seem to reproduce your problem when serializing+encoding and the de-encoding+unserializing...

我应该补充一点,我都没有找到关于这种错误的任何信息:

I should add that I have not been able to find anything about such a bug, in both :

  • php的错误跟踪器
  • 以及json扩展名的SVN历史记录.


现在,如果我尝试使用一个更复杂的对象,并使用一个包含私有成员的类,该成员本身就是一个包含私有属性的对象:

Now, if I try with a more complex object, with a class that contains a private member, which is itself an object which contains a private property :

class A {
    private $priv;
    public function __construct() {
        $this->priv = new B();
    }
}

class B {
    private $b = 10;
}


我得到的行为完全相同:一切正常-在使用与以前完全相同的操作和var_dump()调用时,这是我得到的输出:


I get exactly the same kind of behavior : everything works just fine -- and here is the output I get, when using exactly the same actions and var_dump() calls as before :

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

这里,我也无法重现您所描述的问题.

Here too, I cannot reproduce the problem you describe.


还是,如果我尝试这样做:

Still, if I try this :

var_dump( 
    unserialize( 
        json_decode('{"\u0000MyObject\u0000my_var":[]}')
    )
);

我确实遇到了麻烦:

Fatal error: Cannot access property started with '\0'

但是,考虑一下,如果我尝试将其解码为我自己",我真的看不到你怎么得到这样的JSON字符串...

But, thinking about it, if I try to decode it "myself", I don't really see how you'd have gotten such a JSON string...

您确定其他地方没有问题吗?就像在编码过程中一样?

Are you sure there is not a problem somewhere else ? Like in the encoding process ?

这篇关于json_encode序列化空字节的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆