Gson Builder — 特殊类型 Floats & Doubles

原文链接: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 - 如何解析多态对象

推荐阅读更多精彩内容