I've written the following Spock test to demonstrate a problem that occurs when I deserialize a JSON object containing a number
class GsonFactorySpec extends Specification {
private Gson gson = GsonFactory.instance.gsonInstance
private String JSON = '{"number": 2}'
def 'deserialize a JSON document with an integer value to a Map'() {
when:
Map deserialized = gson.fromJson(JSON, Map)
then:
deserialized.number instanceof Integer
}
}
The test fails because the number is deserialized to a Double
with value 2.0 instead of the Integer
2.
In the factory class where I create the Gson
instance, I tried registering an adapter for instances of Number
@Singleton
class GsonFactory {
private final JsonSerializer<Number> numberSerializer = new JsonSerializer<Number>() {
@Override
JsonElement serialize(Number number, Type type, JsonSerializationContext context) {
Integer intValue = number.toInteger()
intValue == number ? new JsonPrimitive(intValue) : new JsonPrimitive(number)
}
}
Gson getGsonInstance() {
new GsonBuilder().serializeNulls().registerTypeHierarchyAdapter(
Number, numberSerializer).create()
}
}
But it seems this adapter is not invoked during deserialization. Is it possible to force whole numbers to be deserialized as integers?
Update
A new feature added in version 2.8.5 of Gson looks like it might help to solve this issue