Gson doesn't deserialise Long numbers correctly
See original GitHub issueGson shouldn’t cast a number to a Double if a number does not have decimal digits. It’s clearly wrong.
public class GsonVsJackson {
public static void main(String[] args) throws Exception {
testGson();
System.out.println("========================");
testJackson();
}
public static void testGson() {
System.out.println("Testing Gson 2.8");
Gson gson = new Gson();
HashMap<String, Object> newTest = new HashMap<>();
newTest.put("first", 6906764140092371368L);
String jsonString = gson.toJson(newTest);
System.out.println(jsonString); // output ok: {"first":6906764140092371368}
Map<String, Object> mapFromJson = gson.fromJson(jsonString, Map.class);
Number numberFromJson = (Number) mapFromJson.get("first");
System.out.println(numberFromJson.getClass() + " = " + numberFromJson); // java.lang.Double val 6.9067641400923709E18
long longVal = numberFromJson.longValue();
System.out.println(longVal); // output rounded: 6906764140092370944
}
public static void testJackson() throws Exception {
System.out.println("Testing Jackson");
ObjectMapper jackson = new ObjectMapper();
HashMap<String, Object> newTest = new HashMap<>();
newTest.put("first", 6906764140092371368L);
String jsonString = jackson.writeValueAsString(newTest);
System.out.println(jsonString); // output ok: {"first":6906764140092371368}
Map<String, Object> mapFromJson = jackson.readValue(jsonString, Map.class);
Number numberFromJson = (Number) mapFromJson.get("first");
System.out.println(numberFromJson.getClass() + " = " + numberFromJson); // java.math.BigInteger = 6906764140092371368
long longVal = numberFromJson.longValue();
System.out.println(longVal); // output OK: 6906764140092371368
}
}
Kind Regards, Daniele
Issue Analytics
- State:
- Created 6 years ago
- Reactions:32
- Comments:37 (15 by maintainers)
Top Results From Across the Web
How to prevent Gson from converting a long number (a json ...
Gson should only convert a JSON value from 1 to 1.0 if the value property above was of type Float or Double ....
Read more >Gson Deserialization Cookbook - Baeldung
In this cookbook, we're exploring the various ways to unmarshall JSON into Java objects, using the popular Gson library. 1. Deserialize JSON to ......
Read more >Gson User Guide - Google Sites
It is now used by a number of public projects and companies. ... However, Gson can not automatically deserialize the pure inner classes...
Read more >Integer value will always deserialize to be java.lang.Double
com.google.gson.internal.bind.ObjectTypeAdapter.read(JsonReader in) case NUMBER: return in.nextDouble(); It's not so good, is it? Should JsonToken add enum ...
Read more >Leveraging the Gson Library | CodePath Android Cliffnotes
The generator will generated a large number of files that may be a bit ... We do not need any special annotations unless...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
It's not a bug, JSON does not distinguish between integers or floats, and does not care the size of numbers
.Gson is created for java not for javascript. Java does care the data type and size. JSON is not used for javascript only. Hotdog is not dog, there is no need to stick to its literal meaning. Number adapter won’t work for Object type, e.g., ArrayList<Object>.
This is an old issue existed for many years. It’s easy for to fix it. I hope it will be fixed in 2018. Other json libs do not have this bug (I think it is).
It’s not a bug, and gson does it fully legit: JSON does not distinguish between integers or floats, and does not care the size of numbers. Numerics in JSON are just numbers, and
java.lang.Double
is the best and largest primitive-counterpart candidate to hold a JSON number.If you need a long value at a call-site, then just call its
longValue()
method. If, for any particular reason, you need a behavior you are talking about, then you have to implement a custom type adapter factory. Say, something like this (not sure if it’s implemented right, though):However, it can only work if your code can tell Gson to deserialize numbers. This won’t work:
But this will: