我有一个带Unicode字符的字符串。
例如:
$s = '"x9gtjw\u001d91ffd0\u001d92K"';
var_dump($s, json_decode($s));
这给出了输出:
string '"x9gtjw\u001d91ffd0\u001d92K"' (length=29)
string 'x9gtjw91ffd092K' (length=17)
为什么json_decode转换我的unicode符号?
我正在使用PHP 7.2。
我尝试使用标志(例如JSON_INVALID_UTF8_SUBSTITUTE
),但它们没有帮助。
更新:
我需要使用json_decode
而不将\uXXXX
转换为十六进制\xXX
。
例如:
$s = '{"code":"zz\u001d"}';
$json = json_decode($s);
if($json->code == 'zz\u001d') {...}
字符串$s
包含不可见的字符\x1d
。
我尝试将反斜杠转换为双反斜杠-这对输出没有影响。
答案 0 :(得分:1)
字符仍然存在于解码字符串string 'x9gtjw91ffd092K' (length=17)
中,但未显示。 1D是用于组分隔符(不可打印的字符)的ASCII控制代码。
请注意,由于UTF-8字符为\x1d
,并且字符串中有两个,因此字符串长度的大小比显示的字符串(15)大两个(17)。
如果字符为:\u0A1
(倒置感叹号),则UTF-8版本将增加2个额外的字节(\xc2\xa1
)。最多可以存在4个额外的字节(较高的UTF-32 Emojis)。
您的比较不起作用,因为:
您必须将双反斜杠\\\\
加倍才能转义Unicode编码。
$s = '{"code":"zz\\\\u001d"}';
$json = json_decode($s);
if($json->code == 'zz\u001d') {...}
否则\u001d
将在解码时解释。
在此说明更自然的方法(不是问什么,但仍然是解决方案):
PHP包含\uXXXX
转义序列。Reference("Double quoted" section, 1 page down )时,需要双引号“ 。
只需按照以下要求更改检测代码:
$s = '{"code":"zz\u001d"}';
$json = json_decode($s);
if($json->code == "zz\u001d") {...}
{...}
中给出的代码现在将运行。
答案 1 :(得分:1)
您的字符串$s
(它们都是!)不包含任何“不可见字符\ x1d”(根据ASCII的组分隔符(GS))。它们都包含一个文字反斜杠,后跟字母“ u”等。
现在,那里还有什么不对劲:如果打印字符串'a\x0ab'
,您将得到它的原样,减去引号。如果您打印字符串"a\x0ax"
,则将得到一个“ a”和一个“ b”,以换行符分隔。在PHP中,带单引号的字符串文字与带双引号的字符串文字有所不同。
现在,您可能想知道如何避免json_decode()解释\uxxxx
序列。一个简单的答案是:您不能,因为那将违反JSON规范,并且没有理智的解析器会这样做。您基本上可以做两件事:
json_encode()
对预期结果进行编码。