GSON异常 - 打印字段名称,在序列化Nan时会出错

use*_*701 6 java nan gson

我正在使用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)
    ...
Run Code Online (Sandbox Code Playgroud)

有没有办法让Gson打印出有问题的类名/字段名?我可以serializeSpecialFloatingPointValues()按照建议使用该方法,但理想情况下我想了解我的对象有NaN的位置.

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

经过艰苦的踩踏,我认为原因是一个未经双重化的双重原因.我的设置如下:

public class Foo {
    private double price;
}

String jsonFromNet = ...;
Foo foo = Gson.fromJson(jsonFromNet);
Gson.toJson(foo, Foo.class); <-- throws the exception
Run Code Online (Sandbox Code Playgroud)

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

如果我在序列化之前给"price"一个显式值,或者恰好在api json响应中,一切正常.

此外,如果我将"价格"从双倍变为浮动,它似乎并不介意未初始化的状态.

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

谢谢

Sta*_*ili 5

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

Gson()
Run Code Online (Sandbox Code Playgroud)

经过

GsonBuilder().serializeSpecialFloatingPointValues().create()
Run Code Online (Sandbox Code Playgroud)

这里以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)
    }
}
Run Code Online (Sandbox Code Playgroud)


gia*_*olo 3

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

但当我思考这个答案时,我想到了 4 个想法来获取您需要的信息。最终目标是不惜一切代价找到场地,不是吗?

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