原文链接:Gson Builder — Special Values of Floats & Doubles
原文出自:Norman Peitek
译者:無名無
上一节介绍了 lenient 的使用方法,通过设置 lenient 属性,Gson 可以帮我忽略一些错误,保证解析尽量的匹配 Java 对象。本文将了解下 Gson 是如何解析特殊类型 Floats 和 Doubles。
特殊类型 Floats & Doubles
这两种类型是 Java 中常见的类型,用来表示一些特定类型的值,但是在 JSON 中并没有这些类型。
让我们引用 Gson 中关于这个问题的解释:
JSON 规范的第2.4节不允许特殊的double值(NaN,Infinity,-Infinity),但是,Javascript规范(见第4.3.20,4.3.22,4.3.23节)允许这些值作为有效的 Javascript 值。 此外,大多数 JavaScript 引擎将接受 JSON 中的这些特殊值,而没有问题。 因此,在实际应用中,即使不能作为 JSON 规范,但是接受这些值作为有效的 JSON 是有意义的。
我们在 lenient 的使用中知道,序列化是遵循 JSON 标准的,反序列化的问题可以通过设置 lenient 属性来忽略,如果你 Java 对象中包含一个正常的 Floats 或者 Doubles 类型的数据,是可以正常序列化得到 JSON的,如果你传入 Float.POSITIVE_INFINITY 值,Gson 将会抛出异常,因为这个值是不能符合 JSON 标准的。
解决的办法就是通过 GsonBuilder 设置 serializeSpecialFloatingPointValues() 方法
例如:
public class UserFloat {
String name;
Float weight;
public UserFloat(String name, Float weight) {
this.name = name;
this.weight = weight;
}
}
UserFloat user = new UserFloat("Norman", Float.POSITIVE_INFINITY);
Gson gson = new Gson();
UserFloat user = new UserFloat("Norman", Float.POSITIVE_INFINITY);
String usersJson = gson.toJson(user); // will throw an exception
java.lang.IllegalArgumentException: Infinity is not a valid double value as per JSON specification. To override this behavior, use GsonBuilder.serializeSpecialFloatingPointValues() method.
at com.google.gson.Gson.checkValidFloatingPoint(Gson.java:324)
at com.google.gson.Gson$3.write(Gson.java:316)
at com.google.gson.Gson$3.write(Gson.java:302)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:125)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:243)
at com.google.gson.Gson.toJson(Gson.java:669)
at com.google.gson.Gson.toJson(Gson.java:648)
at com.google.gson.Gson.toJson(Gson.java:603)
解决:
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.serializeSpecialFloatingPointValues();
Gson gson = gsonBuilder.create();
UserFloat userFloat = new UserFloat("Norman", Float.POSITIVE_INFINITY);
String usersJson = gson.toJson(userFloat);
System.out.println("userJson:" + usersJson);
注意:有了这个方法,并不意味着你可以随意的配置 JSON 数据格式,建议还是要遵循标准的 JSON 规范。
目标
了解 Gson 序列化不规范的数据结构 Float 和 Double类型,Gson 默认是不支持的,需要单独设置。
练习代码已上传 Github https://github.com/whiskeyfei/Gson-Review 可自行查看。
Gson 系列文章翻译回顾
1、Gson - Java-JSON 序列化和反序列化入门
2、Gson - 映射嵌套对象
3、Gson - Arrays 和 Lists 映射对象
4、Gson - Map 结构映射
5、Gson - Set 集合映射
6、Gson - 空值映射
7、Gson Model Annotations - 如何使用 @SerializedName 更改字段的命名
8、Gson Model Annotations - @SerializedName 匹配多个反序列化名称
9、Gson Builder - 基础和命名规则
10、Gson Builder - 序列化空值
11、Gson Builder - 忽略策略
12、Gson Builder - Gson Lenient 属性
13、Gson Builder - 特殊类型 Floats & Doubles
17、Gson Builder - 如何使用 @Expose 忽略字段
19、Gson Advanced - 映射枚举类型
20、Gson Advanced - 映射循环引用
21、Gson Advanced - 泛型
22、Gson Advanced - 简单自定义序列化 (Part 1)
24、Gson Advanced - 自定义反序列化基础
25、Gson Advanced - 自定义对象实例创建
26、Gson Advanced - 通过 @JsonAdapter 自定义(反)序列化过程
32、Practical Gson - 如何解析多态对象