我一直在阅读一些解决方案,但还没有设法让任何东西工作。
我有一个从 API 调用中读入的 JSON 字符串,它包含 Unicode 字符 - 例如'u00c2'u00a3
是 £ 符号。
我想使用 PHP 将它们转换为 £
或 £
.
我正在调查这个问题并找到了以下代码(使用我的井号进行测试),但它似乎不起作用:
$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)
它不是 UTF-16 编码。它看起来像是虚假编码,因为''uXXXX编码独立于Unicode的任何UTF或UCS编码。 'u00c2'u00a3
真正映射到£
字符串。
你应该拥有的是'u00a3
哪个是 £
的 unicode 代码点。
{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后显示为"?"。
输出正确。
'u00c2 == Â
'u00a3 == £
所以这里没有错。转换为 HTML 实体很容易:
htmlentities($title);
这是使用该函数的更新版本,使用 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;
}