通过JSONObject传递Unicode字符串时出错

时间:2015-06-08 06:50:31

标签: java unicode jsonobject

我必须将unicode字符串传递给JSONObject。

JSONObject json = new JSONObject("{\"One\":\"\\ud83c\\udf45\\ud83c\\udf46\"}");
json.put("Two", "\ud83c\udf45\ud83c\udf46");
System.out.println(json.toString());

但我有这个:

{"One":"","Two":""}

我想要这个:

{"One":"\ud83c\udf45\ud83c\udf46","Two":"\ud83c\udf45\ud83c\udf46"}

2 个答案:

答案 0 :(得分:2)

系统按设计运行。您只是没有考虑到JSON没有要求大多数Unicode字符都以\uXXXX格式进行格式化。某些转义字符必须采用\X格式,控制字符< = 0x1F 必须采用\uXXXX格式,但任何其他字符可能采用\uXXXX格式,但不是必需。您显示的字符不属于这些范围,这就是toString()未以\uXXXX格式对其进行编码的原因。

当你调用new JSONObject(String)时,它会将输入字符串解码为实际的Unicode字符串,就好像你已经这样做了一样:

JSONObject json = new JSONObject();
json.put("One", "\ud83c\udf45\ud83c\udf46");

哪个非常好。您希望 JSONObject在内部保存未转义的Unicode数据。

您被绊倒的地方是JSONObject.toString()没有以\uXXXX格式格式化您的特定Unicode字符。这是完全有效的JSON,但是你不希望它们被格式化(为什么你希望它们以这种方式格式化?)。

查看Java JSONStringer类(实现JSONObject.toString())的源代码,可以看出它只格式化\uXXXX格式的非保留控制字符< = 0x1F,其他非格式保留字符按原样格式化。这符合JSON规范。

要执行您要求的操作,您必须在调用JSONObject.toString()后根据需要手动设置Unicode字符格式,以便正常格式化保留字符和ASCII字符,例如:

JSONObject json = new JSONObject("{\"One\":\"\\ud83c\\udf45\\ud83c\\udf46\"}");
// decodes as if json.put("One", "\ud83c\udf45\ud83c\udf46")
// or json.put("One", "") were called directly ...

json.put("Two", "\ud83c\udf45\ud83c\udf46");
// same as calling json.put("Two", "") ...

String s = json.toString();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < s.length(); ++i)
{
    char ch = s.charAt(i);
    if (ch >= 0x7F)
        sb.append(String.format("\\u%04x", (int) ch));
    else
        sb.append(ch);
}

System.out.println(sb.toString());
// outputs '{"One":"\ud83c\udf45\ud83c\udf46","Two":"\ud83c\udf45\ud83c\udf46"}' as expected ...

答案 1 :(得分:-1)

这样做的一种方法是:

json.put("Two", "\\u" + "d83c" + "\\u" + "df45" + ...);

当您尝试打印JSON时,这将打印字符串文字\ud83c\udf45