PHP json_decode无法处理由Node 12格式良好的json.stringify引起的单个未配对代理



节点12现在使用格式良好的JSON.stringify,它为单独的代理输出转义序列。当有一个单独的代理被转义时,PHP无法对此进行json_decode。

以Node中的以下代码示例为例。

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": "xF0x9Dx98...', false, 512, 7340032)
#1 {main}
thrown in phptest.php on line 36

我希望以下选项JSON_INVALID_UTF8_IGNOREJSON_INVALID_UTF8_SUBSTITUTE能够在PHP 7.3+中使用json_decode,但这根本没有帮助。JSON_THROW_ON_ERROR实际上抛出了一个错误,使其更易于调试。

问题出在Javascript中。

中的字符串包含多字节字符。使用.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
);

最新更新