使用PHP从JSON字符串转换Unicode

时间:2013-01-25 14:30:25

标签: php unicode encoding utf-8 character-encoding

我一直在阅读一些解决方案,但还没有成功完成任何工作。

我有一个JSON字符串,我从API调用中读取它包含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)

3 个答案:

答案 0 :(得分:10)

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之后。

答案 1 :(得分:2)

输出正确。

\u00c2 == Â
\u00a3 == £

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

htmlentities($title);

答案 2 :(得分:1)

此处是使用backend : TkAgg 而非with thetop as ( -- get two first top dates select * from ( select *, ROW_NUMBER() over (partition by id order by schedule_date desc) rownum from @t ) x where x.rownum <= 2 ), thetop2 as ( -- get data from the next row select *, LEAD(schedule_date) over (partition by id order by rownum) second_max_date, LEAD(price) over (partition by id order by rownum) second_max_price from thetop ) -- leave first row select id, schedule_date as first_max_date, price as first_max_price, second_max_date, second_max_price from thetop2 where rownum = 1 order by id; 的函数的更新版本。

preg_replace_callback