I am using Gson to convert my JSON data to a Map<String, Object>
. My JSON has some integer (actually long) fields, and I want them to be parsed as long (obviously). However, Gson parses them as doubles. How can I make Gson parse them as longs/integers? I've seen How to deserialize a list using GSON or another JSON library in Java? but I don't want to create a strongly-typed custom class, I'll be using a Map. I've also seen Android: Gson deserializes Integer as Double and a few other questions which I've thought might be duplicates, but all the answers either point to creating a strongly-typed class, creating extra functions that play role in deserialization or using completely another library.
Isn't there a simple way in Google's own JSON serializer/deserializer that will simply deserialize an integer (yeah, a number without a dot at all) as an integer and not double, as it should have been as default in the first place? If I wanted to send a floating point, I'd be sending 2.0
, not 2
from my server JSON. Why on Earth am I getting a double and how do I get rid of it?
UPDATE: Even though I've clearly explained, some people still don't understand the simple fact that I am not in for another library (e.g. Jackson) and I'm aware of the simple fact that any parser should be able to identify 2.0
as a floating-point and 2
as a pure integer and parse accordingly, so please stop pointing me to telling why it's that way because it's simply incorrect and is not an excuse not to parse integers correctly. So, no, this is not a duplicate of Gson. Deserialize integers as integers and not as doubles.
You can't.
You can't override gson's built-in numbers converters.
I've made a short code test to peek under the hood which types gson tries to find a delegated converter.
package net.sargue.gson;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import org.intellij.lang.annotations.Language;
import java.io.IOException;
import java.util.Map;
public class SO36528727 {
public static void main(String[] args) {
@Language("JSON")
String json = "{\n" +
" \"anInteger\": 2,\n" +
" \"aDouble\": 2.0\n" +
"}";
Gson gson = new GsonBuilder()
.registerTypeAdapterFactory(new LongDeserializerFactory())
.create();
Map<String, Object> m =
gson.fromJson(json,
new TypeToken<Map<String, Object>>() {}.getType());
System.out.println(m.get("aDouble").getClass());
System.out.println(m.get("anInteger").getClass());
}
private static class LongDeserializerFactory
implements TypeAdapterFactory
{
@Override
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
System.out.println("type = " + type);
if (type.getRawType().equals(String.class)) {
TypeAdapter<String> stringAdapter =
gson.getDelegateAdapter(this, TypeToken.get(String.class));
return new TypeAdapter<T>() {
@Override
public void write(JsonWriter out, T value) throws IOException {
stringAdapter.write(out, (String) value);
}
@SuppressWarnings("unchecked")
@Override
public T read(JsonReader in) throws IOException {
String s = stringAdapter.read(in);
System.out.println("s = " + s);
return (T) s;
}
};
} else
return null;
}
}
}
The execution result is this:
type = java.util.Map<java.lang.String, java.lang.Object>
type = java.lang.String
s = anInteger
s = aDouble
class java.lang.Double
class java.lang.Double
So, you can see that gson looks just for two converters: the whole Map<>
thing and the basic String
. But no Double
or Integer
or Number
or even Object
. So you CAN'T override it unless you override it from a higher place like when dealing with a Map
. And that was answered on the thread you reference on the question.