【问题标题】:Why does GSON parse both "\n" and "\\n" as newline?为什么 GSON 将 "\n" 和 "\\n" 都解析为换行符?
【发布时间】:2017-06-26 16:18:11
【问题描述】:

我有以下代码:

public static void main(String[] args) {
    String key = "myjsonkey";
    String baseJson = "{\"" + key + "\":\"my json %svalue\"}";

    String inBackslashAndN = String.format(baseJson, "\\n");
    String inNewline = String.format(baseJson, "\n");

    String outBackslashAndN = valueFromJson(key, inBackslashAndN);
    String outNewLine = valueFromJson(key, inNewline);

    System.out.print("\nInput strings matching: ");
    System.out.println(inBackslashAndN.equals(inNewline));
    System.out.print("Output strings matching: ");
    System.out.println(outBackslashAndN.equals(outNewLine));
}

private static String valueFromJson(String key, String jsonStr) {
    System.out.println("\nINPUT: " + jsonStr);
    JsonObject json = new JsonParser().parse(jsonStr).getAsJsonObject();
    String output = json.get(key).getAsString();
    System.out.println("\nOUTPUT: " + output);
    return output;
}

输出:

INPUT: {"myjsonkey":"my json \nvalue"}

OUTPUT: my json 
value

INPUT: {"myjsonkey":"my json 
value"}

OUTPUT: my json 
value

Input strings matching: false
Output strings matching: true

我的问题是:为什么 JSON 将 "\n" 和 "\\n" 都解析为换行符,有没有办法在不更改原始数据的情况下强制对这两者进行不同的解析?

我使用的是 gson 2.7

编辑:我知道“\n”被处理成新的行控制字符,“\\n”是字符“反斜杠”和Java中字符“n”的序列。我的问题还是一样。

【问题讨论】:

  • 它没有。首先应用 Java 字符串文字处理,因此 JSON 解析器看到的是换行符和 \n,而不是 \n\\n
  • \n 被处理为实际的文字换行符(即 Unicode 000A)。 \\n 等同于字符串“\n”,JSON 解析器(正确地)将 as 解析为换行符,因为“\n”是 JSON 中的换行符。如果你想要一个实际的“\\n”,你可能需要\\\\n。请参阅JSON.org,转义序列位于“char”下方的右侧。当您最终使用多种语言(例如 Java + Regex/JSON)进行操作时,您往往会遇到一些令人困惑的转义序列嵌套。
  • 我知道\\\\n 可以解决问题。我更感兴趣的是在不更改数据的情况下区分两者的解析,只需将标志或不同的读取器传递给解析器
  • @PetrosP 如果你真的想区分,你会想要求 GSON 严格遵循 JSON 标准,该标准不允许 JSON 字符串文字中的控制字符,其中case \nfail 解析。 免责声明:我不知道您是否可以告诉 GSON 严格,但从技术上讲,这正是您所需要的。
  • @Andreas 我相信你可以,通过setLenient

标签: java json parsing gson


【解决方案1】:

JSON 不支持字符串中的文字换行符。来源:http://json.org/

换行符必须表示为\n。 GSON 很可能接受已经转义的斜杠 + n 或文字换行符,并在 JSON 表示中规范化为斜杠 + n,当转换回字符串时,斜杠 + n 再次解析为文字换行符。

【讨论】:

    【解决方案2】:

    \n是换行控制字符,\\n是两个字符,反斜杠和字母n。

    这两种情况都被插入到 JavaScript 字符串“...”中。因此,第二个版本将被转换为换行符。显然,对于第一种情况,字符串中的换行符是允许的。

    【讨论】:

      【解决方案3】:

      为什么 JSON 将 "\n" 和 "\n" 都解析为换行符?

      \n 被处理为实际的文字换行符(即 Unicode 000A)。 \\n 相当于字符串 "\n",JSON 解析器(正确地)将其解析为换行符,因为 "\n" 是 JSON 中的换行符。如果你想要一个实际的“\n”,你可能需要\\\\n。请参阅JSON.org,转义序列位于“char”下方的右侧。当您最终使用多种语言(例如 Java + Regex/JSON)进行操作时,您往往会遇到一些令人困惑的转义序列嵌套。

      JSON 本身在技术上也不支持字符串中的换行符。不过,Gson 会为您解决这个问题,将其转换为“\n”:

      有没有办法在不改变原始数据的情况下强制对这两者进行不同的解析?

      我相信 Gson 没有提供这样做的方法,而且根据 JSON 标准它没有多大意义。你可以:

      String unescaped = myString.replace("\\", "\\\\");
      

      或使用正则表达式:

      String unescaped = myString.replaceAll("\\\\", "\\\\\\\\");
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-08-03
        • 1970-01-01
        • 1970-01-01
        • 2016-06-23
        • 1970-01-01
        • 2018-01-25
        • 1970-01-01
        • 2016-03-20
        相关资源
        最近更新 更多