问题:最近遇到这样一个汉字乱码问题,当我用rfc4627转化json串(看成是[{"key":"value",...}...]形式)时,如果value为汉字时转化没有问题,key为汉字时转化出问题,一个汉字本应该转化为三个unicode码值,但现在只能转化为了一个大约是小于65535的一个值(估计这儿用了某种压缩算法把应该占三位unicode的汉字压缩成占15-16个二进制,也就是现在的小于65535的值).如果都出现乱码可以说rfc4627中没有转化汉字的功能,但现在的问题是当value为汉字时没有问题,但当key为汉字时就出问题,说明rfc4627有汉字转化的代码,但key为汉字时没有加转化代码。
详细描述:我是用rfc4627解码json串时出的问题,如果汉字出现在value上,没有问题;但若出现在key上,则会出现类似的问题,例:
{"a":"b", "c":{"d":"中文"}}没有问题,但
{"a":"b", "c":{"中文":"d"}}就会出现问题
发现问题:rfc2627用xmerl_ucs:from_utf8/1解码时出现的问题:
我跟踪了一下,发现value为汉字不出现问题的原因是在函数parse/2中应用了xmerl_ucs:to_utf8来进行转码,而key的汉字不有执行到这个函数.
解决过程:1.我找到key执行的函数parse_string/2,在里面加上xmerl_ucs:to_utf8函数,这时出现了另一问题,key没问题了,value出问题了.
2.查找发现是对value为汉字的字段进行了两次编码(即执行了两次xmerl_ucs:to_utf8函数)
3.把parse/2中的xmerl_ucs:to_utf8去掉,这时都没有问题了,问题解决
解决方法:1.把函数parse_string/2中的{lists:reverse(Acc), Rest};改为:{xmerl_ucs:to_utf8(lists:reverse(Acc)), Rest};
2.把函数parse[$" | Rest])中的{list_to_binary(xmerl_ucs:to_utf8(Codepoints)), Rest1};修改为:{list_to_binary(Codepoints), Rest1};
忧虑:,担心别的地方调用时会出现问题,像蝴蝶效应,在后面出现更麻烦的问题,我和同事经过仔细研究,在解决这个问题上对我们的系统没有影响,因为我们别的地方没有主动调用过这个模块,调用过这个模块的都需要进行转化!
总结:就这样一个简单的问题,让我用了两天的时间才找到错误的原因。我在找这个原因的时候,是一步步的进行调试,一点点的最后才找到。原来汉字处理模块xmerl_ucs:to_utf8在rfc4627中只对“:”前面的没进行了转化而对“:”后面的进行了转化,导致了对汉字转化的错误。(本想好好研究下xmerl_ucs模块,一放下再也不想拿起了[感慨一下])
另:在rfc4627中注意:
1.在数组或对象中重复的","被转化为一个
2.任何 =<32的字符都被认为是空格
3.接受以0开头的数字
4.不要求最顶层只是对象或数组,任何类型的JSON值都可以。