如何比较JSON对象中字节不同但值相同的Unicode字符串?
解决Unicode字符串语义等价比较问题
这是个很典型的Unicode等价性问题——看起来两个字符串完全一样,但底层编码因为兼容变体的存在而不同,导致直接比较会失败。解决的关键是先对字符串做Unicode兼容性归一化,把语义相同但编码不同的字符统一成标准形式。
问题根源
你遇到的情况是:字符串里的“炙”字有两种Unicode表示:
- 标准CJK统一汉字:
U+7099(对应字符串a里的\u7099) - CJK兼容区变体:
U+F9FB(对应字符串b里的\uf9fb)
这两个字符语义完全相同,但编码值不同,所以直接用==比较会返回False。
解决方案:使用Unicode归一化
大多数编程语言都提供了Unicode归一化工具,核心是通过指定归一化形式,把不同编码的等价字符转换成统一形式。针对你的场景,需要用NFKC(兼容归一化+预组合形式),它会把兼容区的变体字符转换为对应的标准字符。
Python示例代码
import unicodedata # 你的原始字符串 a = u'\u4eba\u53e3\u3058\u3093\u3053\u3046\u306b\u81be\u7099\u304b\u3044\u3057\u3083\u3059\u308b' b = u'\u4eba\u53e3\u3058\u3093\u3053\u3046\u306b\u81be\uf9fb\u304b\u3044\u3057\u3083\u3059\u308b' # 执行NFKC归一化 normalized_a = unicodedata.normalize('NFKC', a) normalized_b = unicodedata.normalize('NFKC', b) # 现在比较就会返回True print(normalized_a == normalized_b) # 输出: True
其他语言的类似实现
比如JavaScript里可以用String.prototype.normalize()方法:
const a = '\u4eba\u53e3\u3058\u3093\u3053\u3046\u306b\u81be\u7099\u304b\u3044\u3057\u3083\u3059\u308b'; const b = '\u4eba\u53e3\u3058\u3093\u3053\u3046\u306b\u81be\uf9fb\u304b\u3044\u3057\u3083\u3059\u308b'; const normalizedA = a.normalize('NFKC'); const normalizedB = b.normalize('NFKC'); console.log(normalizedA === normalizedB); // 输出: true
归一化形式说明
简单解释下常用的几种Unicode归一化形式:
- NFC:把分解的字符组合成预组合形式(比如把基础字符+重音标记合并成单个带重音的字符),但不处理兼容变体。
- NFD:把预组合字符分解成基础字符+标记的形式。
- NFKC:在NFC的基础上,额外处理兼容变体,把语义等价的兼容字符转换为标准字符(正是你需要的)。
- NFKD:在NFD的基础上处理兼容变体。
内容的提问来源于stack exchange,提问作者Seunghoon Baek
相关产品推荐
相关产品推荐

