6

我一直在阅读一些解决方案,但还没有设法让任何工作。

我有一个从 API 调用中读取的 JSON 字符串,它包含 Unicode 字符 -\u00c2\u00a3例如是 £ 符号。

我想使用 PHP 将它们转换为£or 或£.

我正在调查问题并找到以下代码(使用我的磅符号进行测试),但它似乎不起作用:

$title = preg_replace("/\\\\u([a-f0-9]{4})/e", "iconv('UCS-4LE','UTF-8',pack('V', hexdec('U$1')))", '\u00c2\u00a3');

输出是£

我认为这是 UTF-16 编码的是否正确?我如何将这些转换为 HTML 输出?

更新

API 中的 JSON 字符串似乎有 2 或 3 个未转义的 Unicode 字符串,例如:

That\u00e2\u0080\u0099s (right single quotation)
\u00c2\u00a (pound symbol)
4

3 回答 3

11

不是UTF-16 编码。它看起来像是伪造的编码,因为 \uXXXX 编码独立于 Unicode 的任何 UTF 或 UCS 编码。\u00c2\u00a3真的映射到£字符串。

您应该拥有的\u00a3£.

{0xC2, 0xA3} 是此代码点的 UTF-8 编码的 2 字节字符。

如果像我认为的那样,将原始 UTF-8 字符串编码为 JSON 的软件没有注意到它是 UTF-8 并将每个字节盲目编码为转义的 unicode 代码点,那么您需要转换每对 unicode 代码指向一个 UTF-8 编码的字符,然后将其解码为原生 PHP 编码以使其可打印。

function fixBadUnicode($str) {
    return utf8_decode(preg_replace("/\\\\u00([0-9a-f]{2})\\\\u00([0-9a-f]{2})/e", 'chr(hexdec("$1")).chr(hexdec("$2"))', $str));
}

这里的例子:http: //phpfiddle.org/main/code/6sq-rkn

编辑:

如果要修复字符串以获得有效的 JSON 字符串,则需要使用以下函数:

function fixBadUnicodeForJson($str) {
    $str = preg_replace("/\\\\u00([0-9a-f]{2})\\\\u00([0-9a-f]{2})\\\\u00([0-9a-f]{2})\\\\u00([0-9a-f]{2})/e", 'chr(hexdec("$1")).chr(hexdec("$2")).chr(hexdec("$3")).chr(hexdec("$4"))', $str);
    $str = preg_replace("/\\\\u00([0-9a-f]{2})\\\\u00([0-9a-f]{2})\\\\u00([0-9a-f]{2})/e", 'chr(hexdec("$1")).chr(hexdec("$2")).chr(hexdec("$3"))', $str);
    $str = preg_replace("/\\\\u00([0-9a-f]{2})\\\\u00([0-9a-f]{2})/e", 'chr(hexdec("$1")).chr(hexdec("$2"))', $str);
    $str = preg_replace("/\\\\u00([0-9a-f]{2})/e", 'chr(hexdec("$1"))', $str);
    return $str;
}

编辑 2:修复了以前的函数,将任何错误的 unicode 转义 utf-8 字节序列转换为等效的 utf-8 字符。

请注意,其中一些可能来自 Word 等编辑器的字符无法翻译为 ISO-8859-1,因此将显示为“?” ut8_decode 之后。

于 2013-01-25T14:43:20.583 回答
3

输出是正确的。

\u00c2 == Â
\u00a3 == £

所以这里没有错。并且转换为 HTML 实体很容易:

htmlentities($title);
于 2013-01-25T14:41:19.390 回答
3

这是使用preg_replace_callback代替的函数的更新版本preg_replace

function fixBadUnicodeForJson($str) {
    $str = preg_replace_callback(
    '/\\\\u00([0-9a-f]{2})\\\\u00([0-9a-f]{2})\\\\u00([0-9a-f]{2})\\\\u00([0-9a-f]{2})/',
    function($matches) { return chr(hexdec("$1")).chr(hexdec("$2")).chr(hexdec("$3")).chr(hexdec("$4")); },
    $str
);
    $str = preg_replace_callback(
    '/\\\\u00([0-9a-f]{2})\\\\u00([0-9a-f]{2})\\\\u00([0-9a-f]{2})/',
    function($matches) { return chr(hexdec("$1")).chr(hexdec("$2")).chr(hexdec("$3")); },
    $str
);
    $str = preg_replace_callback(
    '/\\\\u00([0-9a-f]{2})\\\\u00([0-9a-f]{2})/',
    function($matches) { return chr(hexdec("$1")).chr(hexdec("$2")); },
    $str
);
    $str = preg_replace_callback(
    '/\\\\u00([0-9a-f]{2})/',
    function($matches) { return chr(hexdec("$1")); },
    $str
);
    return $str;
}
于 2018-08-03T16:56:13.270 回答