php - PHP json_decode 不适用于由节点 12 格式良好的 JSON.stringify 引起的单个未配对代理项
问题描述
节点 12 现在使用格式良好的 JSON.stringify,它为单独的代理输出转义序列。当有一个单独的代理被转义时,PHP 无法对此进行 json_decode。
以 Node.js 中的以下代码示例为例。
var a = ' ';
JSON.stringify(a.slice(0, 15));
// Node 10 output:
'"�"';
// Node 12 output:
'"\\ud835"'
然后,此响应以 JSON 格式发送到 PHP 服务器并进行解码。这是发生错误的地方。Node10 的输出过去可以与 PHP json_decode 一起正常工作,但它不再适用于 Node12 的输出。
我简化了 NODE->PHP 示例,见下文。
<?php
$string = '{"string": "\\ud835"}';
var_dump(json_decode($string, false, 512, JSON_THROW_ON_ERROR | JSON_INVALID_UTF8_IGNORE | JSON_INVALID_UTF8_SUBSTITUTE));
// Output:
Fatal error: Uncaught JsonException: Single unpaired UTF-16 surrogate in unicode escape in phptest.php:36
Stack trace:
#0 phptest.php(36): json_decode('{"string": "\xF0\x9D\x98...', false, 512, 7340032)
#1 {main}
thrown in phptest.php on line 36
我希望以下选项JSON_INVALID_UTF8_IGNORE
或JSON_INVALID_UTF8_SUBSTITUTE
在 PHP 7.3+ 中与 json_decode 一起使用,但它根本没有帮助。JSON_THROW_ON_ERROR
实际上会引发错误以使其更易于调试。
解决方案
问题出在Javascript中。
a 中的字符串包含多字节字符。使用 a.slice(0, 15) 你会得到 15 个字节,而不是 15 个字符,并创建一个无效的 utf-8 字符串。多字节字符可能不会被破坏。
更新:
我认为选项 JSON_INVALID_UTF8_IGNORE 和 JSON_INVALID_UTF8_SUBSTITUTE 用于 json_encode () 而不是为 json_decode () 清理无效 JSON。干净的解决方案是在 Javascript 页面上提供有效的 JSON。
肮脏的解决方案是尝试用 PHP 纠正无效的 JSON:
$json = preg_replace_callback(
'~\\\u[a-d0-9]{4}~iu',
function($found){
if(json_decode('"'.$found[0].'"')){
return $found[0];
}
return ""; //or "?"
},
$invalidJson
);
推荐阅读
- javascript - 删除数组中的前缀 y 以将其用于图形的 ax 轴
- php - 更新到最新版本后已定义 Joomla 常量 _QQ_
- android - 在 LinearLayout 中将 TableLayout 居中
- java - Springboot组合安全(Oauth和form)配置
- php - PHP 关联数组的形成
- here-api - 来自 chrome 的 HERE Maps SSL 响应
- java - 我们可以使用 java 实现注册连续查询通知吗?如果是,那么如何?
- c - 使用堆栈将递归实现转换为迭代实现
- java - 类没有自动生成
- c++ - 在 Code::Blocks 中使用 SFML