Gson Builder Floats 和 Doubles 的特殊值

在上一篇 Gson 的文章中,我们研究了使 JSON 转换降低标准的选项。 Lenient 允许传入的 JSON 在某种程度上是非标准的,Gson 仍然能够将其解析为 Java 对象。 在这篇文章中,我们将研究一个允许非标准输入的案例:Floats 和 Doubles 的特殊值(如 Float.NEGATIVE_INFINITY)。


Floats 和 Doubles 的特殊值

在 Java 中,需要用 float 和 double 值来表达一些边缘情况。 因此,Float.NEGATIVE_INFINITYFloat.POSITIVE_INFINITY 和 Float.NaN 的常量以及它们的双重对应物从一开始就在 Java 语言中。 不幸的是,JSON 规范没有看到这些边缘值的价值,也没有将其作为规范的一部分。

让我们在这个问题上引用 Gson 文档:

JSON 规范的第 2.4 节不允许特殊的双精度值(NaN、Infinity、-Infinity)。 但是,Javascript 规范(参见第 4.3.20、4.3.22、4.3.23 节)允许这些值作为有效的 Javascript 值。 此外,大多数 JavaScript 引擎将毫无问题地接受 JSON 中的这些特殊值。 因此,在实际层面上,接受这些值作为有效的 JSON 是有意义的,即使 JSON 规范不允许它们。

还记得在上一篇文章中我们写道,当谈到 JSON 标准时,Gson 在反序列化期间非常灵活,而在序列化期间非常严格? 第一部分仍然正确,但是这个Floats/Doubles特殊值主题是 Gson 可以故意违反标准的唯一例外。

让我们明确一点:如果传入的 JSON 使用这些特殊的 Floats/Doubles 值中的一个或多个,默认情况下会反序列化它而不会出现任何问题。

如果我们将 Float.POSITIVE_INFINITY 作为值传递,Gson 将抛出异常,因为它无法转换它并且符合标准。 如果我们需要传递这些值,则需要专门启用那些使用 GsonBuilder 的转换。 Gson 提供了方法 serializeSpecialFloatingPointValues() 来做到这一点。

是时候看一个例子了。 我们创建了一个用户类,它还存储了一个描述权重的 Float 值。

public class UserFloat {  
    String name;
    Float weight;

    public UserFloat(String name, Float weight) {
        this.name = name;
        this.weight = weight;
    }
}

现在,由于节日的美食对我产生了负面影响,而且我最近体重增加了很多,所以我需要像这样创建我的用户实例:

UserFloat user = new UserFloat("jiyik", Float.POSITIVE_INFINITY);  

如果我们把它传递给 Gson,它会抛出一个异常:

Gson gson = new Gson();

UserFloat user = new UserFloat("jiyik", Float.POSITIVE_INFINITY);

String usersJson = gson.toJson(user); // 这里将会抛出异常  

Gson 会给我们抛出一个 IllegalArgumentException 异常,它会声明

根据 JSON 规范,无穷大不是有效的双精度值。 要覆盖此行为,请使用 GsonBuilder.serializeSpecialFloatingPointValues() 方法。

异常消息很有帮助,并且已经将我们推荐了解决方案。 我们需要使用 GsonBuilder:

Float.POSITIVE_INFINITY

这将毫无例外地创建一个 usersJson 和正确的内容:

GsonBuilder

当然,由于这不是 100% 标准,我们需要确保我们自己的 API 可以处理这些异常值。

免责声明:
1.本站所有内容由本站原创、网络转载、消息撰写、网友投稿等几部分组成。
2.本站原创文字内容若未经特别声明,则遵循协议CC3.0共享协议,转载请务必注明原文链接。
3.本站部分来源于网络转载的文章信息是出于传递更多信息之目的,不意味着赞同其观点。
4.本站所有源码与软件均为原作者提供,仅供学习和研究使用。
5.如您对本网站的相关版权有任何异议,或者认为侵犯了您的合法权益,请及时通知我们处理。
火焰兔 » Gson Builder Floats 和 Doubles 的特殊值