I'm using Gson, ran into a problem serializing an object:
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)
...
Is there a way to have Gson print the class name/field name it is having a problem with? I can use the serializeSpecialFloatingPointValues()
method as suggested, but ideally I'd like to understand where my objects have a NaN.
-------- Update ----------------
After painstakingly stepping through this, I think the cause is an uninitiatlized double. My setup looks like this:
public class Foo {
private double price;
}
String jsonFromNet = ...;
Foo foo = Gson.fromJson(jsonFromNet);
Gson.toJson(foo, Foo.class); <-- throws the exception
The return json from my api is not including the attribute "price", so I guess the member variable "d" is left uninitialized. When I go to serialize it, gson throws the error.
If I give "price" an explicit value before serialization, or it happens to be in the api json response, everything works fine.
Also if I change "price" from a double to a float, it doesn't seem to mind the uninitialized state.
I'll look into GsonBuilder.serializeSpecialFloatingPointValues() now, I just wonder how the double gets serialized in this state. I'd be ok with a default value of zero or something.
Thanks
Gson can serialize static nested classes quite easily. NOTE: The above class B can not (by default) be serialized with Gson.
As you can see, Gson will ignore the unknown fields and simply match the fields that it's able to.
By default, GSON excludes transient and static fields from the serialization/deserialization process.
Gson is the main actor class of Google Gson library. It provides functionalities to convert Java objects to matching JSON constructs and vice versa. Gson is first constructed using GsonBuilder and then toJson(Object) or fromJson(String, Class) methods are used to read/write JSON constructs.
The easiest way to get around this problem of Nan Parsing is to replace the default
Gson()
by
GsonBuilder().serializeSpecialFloatingPointValues().create()
Here is an example of Android Unit test class as an example (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)
}
}
Strictly speaking the answer is no. I checked source code and, to my best knowledge, I cannot see a point where you can customize behavior getting what you need using Gson.
But when thinking about this answer, 4 ideas come to my mind to get anyway the info you need. The end goal is to spot the field at any cost, isn't it?.
checkValidFloatingPoint
method and check value of boundField.name
in com.google.gson.internal.bind.Adapter<T>.writ
e. That's the offending field.serializeSpecialFloatingPointValues()
, serialize to the JSON string, then using a regular expression search, find every Nan in string. Nearby there's the field name or the array field name you are looking for.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With