GSON / JSON:奇怪的特殊字符(变音符号)问题

时间:2011-10-24 10:21:53

标签: json gson diacritics

在尝试使用GSON处理JSON响应时(输出来自flickr API,以防你问)我遇到了我所描述的某些特殊字符的奇怪编码:

Original JSON response

以下是它的十六进制视图:

Hex View of Original JSON response

'u'后跟'双点'是德国人'ü',这就是我的困惑开始的地方。就好像有人拿了这个字母并把它撕成两半,然后对这两个字母进行编码。下图显示了在'ü'被正确编码的情况下我所期望的十六进制编码:

Expected Hex View

更奇怪的是,在我预计会出现问题的情况下(即亚洲字符集),一切似乎都很好,例如“title”:“ナガレテユク···”

问题:

  1. 对于reposonse,是否有一些flickrAPI奇怪或正确的JSON编码?或者是相当正确编码的JSON和它的GSON未能将此响应“重组”到原始的'ü'中。或者标题信息的作者是否只是将其搞砸了?
  2. 我如何解决这个问题(如果它是JSON或GSON那么搞乱,如果是作者那么显然不能做任何事情)。我怎么知道“其他”字符会受到什么影响(ö和ä会浮现在脑海中,但可能会有更多'特殊情况')。

1 个答案:

答案 0 :(得分:5)

您看到的是Unicode decomposition的案例:

德语变音符号等字符可以用两种方式表达:

  • 将更传统的预合成表单作为单个字符ü
  • 以分解形式作为基本字符u后跟combining diaeresis ̈_(我必须在此处使用下划线才能显示它,因为它不应该独立存在,它确实是只是“徘徊点”)

如果您收到类似的内容,可以使用java.text.Normalizer(自Java 1.6以来可用)轻松转换为预先组合的表单:

String decomposed = "Mitgef\u0308hl";
printChars(decomposed); // Mitgefühl -- [M, i, t, g, e, f, u, ̈, h, l]
String precomposed = Normalizer.normalize(decomposed, Form.NFC);
printChars(precomposed); // Mitgefühl -- [M, i, t, g, e, f, ü, h, l]

// Normalizing with NFC again doesn't hurt:
String precomposedAgain = Normalizer.normalize(precomposed, Form.NFC);
printChars(precomposedAgain); // Mitgefühl -- [M, i, t, g, e, f, ü, h, l]
...

static void printChars(String s) {
  System.out.println(s + " -- " + Arrays.toString(s.toCharArray()));
}

正如您所看到的,将NFC应用于已经预先组合的字符串并不会造成伤害。

请注意,打印String将在任何支持Unicode的终端上正确显示,只有在打印字符数组时才能看到分解和预组合表单之间的区别。

可能的来源可能是MacOS,它倾向于以分解形式对事物进行编码,但很奇怪Flickr并没有规范化这些东西。