Gson Builder 使用 Lenient 放宽 Gson 的转换标准

JSON 内容的格式必须满足一些特定的规则才能符合标准。 该标准在 RFC4627 规范中进行了描述。 它为键和值的分离方式、数组的结构等奠定了基础。 在这篇文章中,我们将探讨 Gson 与 JSON 规范的关系。


默认 Lenient

首先,当 Gson 序列化 Java 对象时,它会创建一个 100% 符合标准的 JSON。 有趣的部分是 Gson 在反序列化过程中的行为方式!

在内部,Gson 使用了一个 JsonReader 类。 该类可以选择 lenient 或者选用其他的非 lenient。 默认情况下它是不使用 lenient的,这意味着它只接受兼容的 JSON 输入。 如果 JSON 违反了结构规则之一,则 JsonReader 和 Gson 将抛出异常。 但是,JsonReader 具有宽松的可选设置。 然后,也只有到那时,它才会兼容某些违规行为,并尝试最好甚至读取格式有问题的 JSON。

让我们引用一些非标准 JSON 元素的文档:

  • 以非执行前缀 “)]}'\n” 开头的流。
  • 包含多个顶级值的流。 使用严格的解析,每个流必须只包含一个顶级值。
  • 任何类型的顶级值。 使用严格解析,顶级值必须是对象或数组。
  • 数字可以是 NaN 或无穷大。
  • 以 // 或 # 开头并以换行符结尾的行尾注释。
  • 以 /* 开头并以 */ 结尾的 C 样式注释。 此类注释可能不会嵌套。
  • 未加引号或“单引号”的名称。
  • 未加引号或“单引号”的字符串。
  • 数组元素用 ; 分隔 代替 ,
  • 不必要的数组分隔符。 这些被解释为好像 null 是省略的值。
  • 名称和值由 = 或 => 分隔,而不是 :。
  • 由 ; 分隔的名称/值对 代替 ,

所有这些对我们使用 Gson 有何影响? 从理论上讲,Gson(与 JsonReader 不同)在默认情况下已经很宽松了。 因此,如果我们的 JSON 不正确,通常我们不需要启用它。 不幸的是,Gson 在这个问题上的具体表现似乎有些混乱。 随着事情的发展,我们会为大家进行更新。

大家需要记住的是,在 JSON 反序列化方面,Gson 可以选择更加宽容。 如果要启用它,请使用 GsonBuilder:

GsonBuilder gsonBuilder = new GsonBuilder();  
gsonBuilder.setLenient();  
Gson gson = gsonBuilder.create();  

让你的 Gson 实例宽松可以帮助解决一些结构性问题。 然而,宽大的选项只能做这么多。 如果违规超出了我们在上面向大家展示的一个示例,Gson 将抛出 MalformedJsonException。 如果我们遇到其中之一,可能需要检查自己的 JSON 及其结构有效性。 几乎在所有情况下,问题的根源都是存在的。

我们建议使用 JSONLint 之类的工具来验证我们的 JSON。