PHP中解码JSON时如何保留Unicode转义字符(如<)
PHP解码JSON时如何保留Unicode转义字符?
问题背景
处理包含Unicode转义字符(如\u003C对应<)的JSON字符串时,需要在解码为关联数组时保持这些转义字符原样(即\u003C不转为<),后续编码回JSON时也保留原始转义格式。以下是示例代码及预期需求:
// 原始JSON字符串 $json = '{"Code_Injecting":{"Code":"\u003Cstyle\u003E div#example { display: none; }\u003C/style\u003E"}, "RemoveKey":"removeValue"}'; // 当前解码逻辑(会自动转换Unicode转义) $array = json_decode($json, true); // 业务操作:删除指定键 if (isset($array['RemoveKey'])) { unset($array['RemoveKey']); } // 编码回JSON $newJson = json_encode($array, JSON_UNESCAPED_SLASHES); // 预期输出:{"Code_Injecting":{"Code":"\u003Cstyle\u003E div#example { display: none; }\u003C/style\u003E"}}
解决方案
PHP的json_decode默认会自动解析Unicode转义序列,没有直接参数禁用该行为,需通过变通方法实现:
方法:临时替换转义标记+递归恢复
核心思路是先把JSON中的\u替换为临时字符串,让json_decode无法识别为Unicode转义,解码后再恢复标记,最后处理编码时的转义问题。
// 原始JSON字符串 $json = '{"Code_Injecting":{"Code":"\u003Cstyle\u003E div#example { display: none; }\u003C/style\u003E"}, "RemoveKey":"removeValue"}'; // 1. 替换Unicode转义前缀为临时标记 $tempJson = str_replace('\u', '__UNICODE_TEMP__', $json); // 2. 解码JSON $array = json_decode($tempJson, true); if (json_last_error() !== JSON_ERROR_NONE) { die('JSON解码错误: ' . json_last_error_msg()); } // 3. 递归遍历数组,恢复Unicode转义前缀 function restoreUnicode(&$value) { if (is_string($value)) { $value = str_replace('__UNICODE_TEMP__', '\u', $value); } elseif (is_array($value)) { array_walk_recursive($value, 'restoreUnicode'); } } restoreUnicode($array); // 4. 执行业务逻辑(删除指定键) if (isset($array['RemoveKey'])) { unset($array['RemoveKey']); } // 5. 编码回JSON并修正转义 $newJson = json_encode($array, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); // 把json_encode自动转义的\\u还原为\u $newJson = str_replace('\\u', '\u', $newJson); // 输出结果 echo $newJson;
原理说明
- 临时替换:将
\u替换为__UNICODE_TEMP__,使json_decode不会将其识别为Unicode转义序列,从而保留原始的003C等字符。 - 递归恢复:解码后遍历数组,把临时标记替换回
\u,确保数组中存储的是\u003C格式的字符串。 - 修正编码转义:
json_encode会将字符串中的\自动转义为\\,因此需要最后一步替换\\u为\u,得到符合预期的JSON格式。
注意事项
- 临时标记需确保不会与JSON中的其他内容冲突,建议使用唯一且无意义的字符串。
- 若JSON结构复杂(包含嵌套数组/对象),必须使用递归遍历恢复标记,避免遗漏。
内容的提问来源于stack exchange,提问作者Jayant Singh
相关产品推荐
相关产品推荐

