【发布时间】:2014-04-26 03:45:00
【问题描述】:
EDIT2:问题在于我的 Perl 客户端如何解释 PHP 的 json_encode 的输出,默认情况下输出 Unicode 代码点。将JSON Perl 模块置于 ascii 模式 (my $j = JSON->new()->ascii();) 使事情按预期工作。
我正在与一个用 PHP 编写的返回 JSON 的 API 交互,使用一个用 Perl 编写的客户端,然后将修改后的 JSON 版本提交回同一个 API。 API 从编码为 UTF8 的 PostgreSQL 数据库中提取值。我遇到的是 API 返回不同的字符编码,即使 PHP 从数据库接收到的值是正确的 UTF-8。
我已经设法用几行 PHP (5.3.24) 重现了我所看到的内容:
<?php
$val = array("Millán");
print json_encode($val)."\n";
根据the PHP documentation,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 已由 json_encode 更改为 "Unicode" lower case a-acute。
如何防止 PHP/json_encode 切换此变量的编码?
编辑:有趣的是,如果我将字符串文字更改为utf8_encode("Millán"),那么事情就会按预期工作。 utf8_encode 文档说该函数仅支持 ISO-8859-1 输入,所以我对它的工作原理有点困惑。
【问题讨论】:
-
\uXXXX转义序列是在 JSON 数据格式中编码任意字符的一种完全有效的方法。从 JSON 解码时,您将恢复您的角色。除此之外,我还有什么遗漏吗? -
嗯,\u00e1 与 \u00c3\u00a1 不同 - 其中一个是有效的 utf8 字符,另一个不是。 PHP 能够以某种方式将 \u00e1 翻译回 utf8。我遇到的问题是,当带有 \u00e1 的编码字符串离开 PHP 世界并被例如解释时Perl,然后传回 PHP,
json_decodethrowsJSON_ERROR_UTF8 -
\u00e1代表 U+00E1,字符“á”。\u00c3\u00a1肯定不是“á”。 -
U+C3A1 或 \uc3a1 是字符 쎡。不要将 Unicode 代码点(U+... 和 \u...)与物理 UTF-* 编码混淆!也许阅读What Every Programmer Absolutely, Positively Needs To Know About Encodings And Character Sets To Work With Text
-
感谢您的链接,它把我推向了正确的方向。对我的 Perl 客户端进行的小改动已修复:
my $j = JSON->new()->ascii();如果您提交答案,我会接受。
标签: php json perl encoding utf-8