EDIT2:问题在于我的Perl客户端如何解释PHP json_encode
的输出,默认情况下输出Unicode代码点。将JSON
Perl模块置于ascii模式(my $j = JSON->new()->ascii();
(使事情按预期工作。
我正在使用用Perl编写的客户端与用PHP编写的返回JSON的API进行交互,然后将JSON的修改版本提交回同一API。该 API 从编码为 UTF8 的 PostgreSQL 数据库中提取值。我遇到的是 API 返回不同的字符编码,即使 PHP 从数据库接收的值是正确的 UTF-8。
我已经设法用几行 PHP (5.3.24( 重现了我所看到的内容:
<?php
$val = array("Millán");
print json_encode($val)."'n";
根据 PHP 文档,string literals are encoded ... in whatever fashion [they are] encoded in the script file
.
以下是十六进制转储文件编码(UTF-8 小写 a-acute = c3 a1(:
$ grep ill test.php | od -An -t x1c
24 76 61 6c 20 3d 20 61 72 72 61 79 28 22 4d 69
$ v a l = a r r a y ( " M i
6c 6c c3 a1 6e 22 29 3b 0a
l l 303 241 n " ) ; 'n
这是 PHP 的输出:
$ php -f test.php | od -An -t x1c
5b 22 4d 69 6c 6c 5c 75 30 30 65 31 6e 22 5d 0a
[ " M i l l ' u 0 0 e 1 n " ] 'n
UTF-8 小写 a-acute 已更改为 "Unicode" 小写 a-acute json_encode
。
如何防止 PHP/json_encode
切换此变量的编码?
编辑:有趣的是,如果我将字符串文字更改为utf8_encode("Millán")
那么事情就会按预期工作。utf8_encode
文档说该功能仅支持 ISO-8859-1 输入,所以我对为什么有效有点困惑。
这完全是基于误解。 json_encode
将非 ASCII 字符编码为 Unicode 转义序列'u....
。这些序列不引用任何 UTF 编码中的任何物理字节编码,它通过其 Unicode 码位引用字符。U+00E1 是字符 á
的 Unicode 码位。任何正确的 JSON 解析器都会将'u00e1
解码回字符"á"。这里没有问题。
请尝试以下命令来解决他们的问题。
<?php
$val = array("Millán");
print json_encode($val, JSON_UNESCAPED_UNICODE);
注意:将JSON_UNESCAPED_UNICODE参数添加到json_encode函数中以保留原始值。
对于 python,这个 将 json.dumps 中的 utf-8 文本保存为 UTF8,而不是 ''u 转义序列