【问题标题】:UTF-8 issue with PHP's json_decodePHP 的 json_decode 的 UTF-8 问题
【发布时间】: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 documentationstring 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_decode throws JSON_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-&gt;new()-&gt;ascii(); 如果您提交答案,我会接受。

标签: php json perl encoding utf-8


【解决方案1】:

这完全是基于一种误解。 json_encode 将非 ASCII 字符编码为 Unicode 转义序列 \u....。这些序列不引用任何 UTF 编码中的任何物理 byte 编码,它通过其 Unicode 代码点引用字符。 U+00E1 是字符 á 的 Unicode 代码点。任何正确的 JSON 解析器都会将\u00e1 解码回字符“á”。这里没有问题。

【讨论】:

    【解决方案2】:

    尝试下面的命令来解决他们的问题。

    <?php
    $val = array("Millán");
    print json_encode($val, JSON_UNESCAPED_UNICODE);
    

    注意:在 json_encode 函数中添加 JSON_UNESCAPED_UNICODE 参数以保持原始值。

    对于python,这个Saving utf-8 texts in json.dumps as UTF8, not as \u escape sequence

    【讨论】:

    • 该标志在 PHP 5.4.X 中可用 - 不幸的是,我坚持使用 5.3.24
    • 升级您的版本,如果不能,请与您的网络主机商联系或更改它。
    猜你喜欢
    • 2011-05-03
    • 1970-01-01
    • 2011-11-30
    • 1970-01-01
    • 2011-06-05
    • 2011-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多