8

我正在使用 Gson,遇到了序列化对象的问题:

java.lang.IllegalArgumentException: NaN 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:296)
    ...

有没有办法让 Gson 打印它有问题的类名/字段名?我可以serializeSpecialFloatingPointValues()按照建议使用该方法,但理想情况下我想了解我的对象在哪里有一个 NaN。

- - - - 更新 - - - - - - - -

在煞费苦心地走过这一步之后,我认为原因是一个不熟悉的替身。我的设置如下所示:

public class Foo {
    private double price;
}

String jsonFromNet = ...;
Foo foo = Gson.fromJson(jsonFromNet);
Gson.toJson(foo, Foo.class); <-- throws the exception

我的 api 的返回 json 不包括属性“price”,所以我猜成员变量“d”未初始化。当我去序列化它时,gson 会抛出错误。

如果我在序列化之前给“价格”一个明确的值,或者它恰好在 api json 响应中,那么一切正常。

此外,如果我将“价格”从 double 更改为 float,它似乎并不介意未初始化的状态。

我现在将研究 GsonBuilder.serializeSpecialFloatingPointValues(),我只是想知道双精度如何在这种状态下被序列化。我可以使用默认值零或其他值。

谢谢

4

2 回答 2

4

解决 Nan Parsing 问题的最简单方法是替换默认值

Gson()

经过

GsonBuilder().serializeSpecialFloatingPointValues().create()

这里以Android单元测试类为例(Kotlin)

import com.google.gson.GsonBuilder
import org.junit.Assert
import org.junit.Test

class NanGSONParsingTest {
    data class FloatContainer(val includedFloat: Float)

    @Test
    fun gsonCanHandleNanParsing() {
        val container = FloatContainer(Float.NaN)
        val gson = GsonBuilder().serializeSpecialFloatingPointValues().create()
        val jsonString = gson.toJson(container)//{"includedFloat":NaN}
        val parsedBackContainer = gson.fromJson<FloatContainer>(jsonString, FloatContainer::class.java)
        Assert.assertEquals(container,parsedBackContainer)
    }
}
于 2020-01-10T09:39:04.287 回答
2

严格来说,答案是否定的。我检查了源代码,据我所知,我看不到您可以自定义行为以获得使用 Gson 所需的内容。

但是在考虑这个答案时,我想到了 4 个想法来获得你需要的信息。最终目标是不惜一切代价发现该领域,不是吗?

  1. 下载Gson代码,在checkValidFloatingPoint方法抛出异常前下断点,检查e中boundField.name的值。com.google.gson.internal.bind.Adapter<T>.writ那是有问题的领域。
  2. 下载 Gson 代码并自定义上一点的方法,以在捕获 IllegalArgumentException 时打印出违规字段。(提出补丁;))
  3. 使用serializeSpecialFloatingPointValues(), 序列化为 JSON 字符串,然后使用正则表达式搜索,找到字符串中的每个 Nan。附近有您要查找的字段名称或数组字段名称。
  4. 构建您自己的类扫描器,通过反射检查每个双字段以检查值是否为空。当然,在这种情况下,不需要 Gson。无论如何,这将是一个有趣的练习。
于 2013-09-20T20:52:15.853 回答