Recently I faced this problem. I have data in the below format.
[{
"a": 1,
"b": 2
}, {
"c": 3,
"d": 4
}]
When I am trying to convert the above data to ‘List<Map<String, Object>>’, gson converting integers to real values like below.
[{
"a": 1.0,
"b": 2.0
}, {
"c": 3.0,
"d": 4.0
}]
As you observe above snippet, 1 is converted to 1.0, 2 is converted to 2.0 etc.,
App.java
package com.sample.app.util;
import java.util.List;
import java.util.Map;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
public class App {
public static void main(String args[]) {
String json = "[{\"a\":1,\"b\":2},{\"c\":3,\"d\":4}]";
Gson gson = new Gson();
List<Map<String, Object>> list = gson.fromJson(json, new TypeToken<List<Map<String, Object>>>() {
}.getType());
for (Map<String, Object> item : list) {
System.out.println(item);
}
}
}
Output
{a=1.0, b=2.0}
{c=3.0, d=4.0}
Root cause of this behavior?
read() method in ObjectTypeAdapter class is implemented like below.
public Object read(JsonReader in) throws IOException {
JsonToken token = in.peek();
switch (token) {
case BEGIN_ARRAY:
......
case NUMBER:
return in.nextDouble();
......
}
}
As you see above snippet, when a token is of type NUMBER encountered, it is converted to double by default.
How to resolve the above problem?
Create a custom deserializer that handles number type correctly.
DoubleToIntDeserializer.java
package com.sample.app.util;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.google.gson.JsonArray;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.internal.LinkedTreeMap;
public class DoubleToIntDeserializer implements JsonDeserializer<Map<String, Object>> {
@Override
@SuppressWarnings("unchecked")
public Map<String, Object> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
return (Map<String, Object>) read(json);
}
public Object read(JsonElement jsonElement) {
if (jsonElement.isJsonArray()) {
List<Object> list = new ArrayList<Object>();
JsonArray jsonArray = jsonElement.getAsJsonArray();
for (JsonElement anArr : jsonArray) {
list.add(read(anArr));
}
return list;
}
if (jsonElement.isJsonObject()) {
Map<String, Object> map = new LinkedTreeMap<String, Object>();
JsonObject jsonObject = jsonElement.getAsJsonObject();
Set<Map.Entry<String, JsonElement>> entitySet = jsonObject.entrySet();
for (Map.Entry<String, JsonElement> entry : entitySet) {
map.put(entry.getKey(), read(entry.getValue()));
}
return map;
}
if (jsonElement.isJsonPrimitive()) {
JsonPrimitive jsonPrimitive = jsonElement.getAsJsonPrimitive();
if (jsonPrimitive.isBoolean()) {
return jsonPrimitive.getAsBoolean();
}
if (jsonPrimitive.isString()) {
return jsonPrimitive.getAsString();
}
if (jsonPrimitive.isNumber()) {
Number num = jsonPrimitive.getAsNumber();
if (Math.ceil(num.doubleValue()) == num.longValue())
return num.longValue();
return num.doubleValue();
}
}
return null;
}
}
Build Gson instance using this deserializer.
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(new TypeToken<Map<String, Object>>() {}.getType(), new DoubleToIntDeserializer());
Gson gson = gsonBuilder.create();
App.java
package com.sample.app.util;
import java.util.List;
import java.util.Map;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
public class App {
public static void main(String args[]) {
String json = "[{\"a\":1,\"b\":2},{\"c\":3,\"d\":4}]";
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(new TypeToken<Map<String, Object>>() {
}.getType(), new DoubleToIntDeserializer());
Gson gson = gsonBuilder.create();
List<Map<String, Object>> list = gson.fromJson(json, new TypeToken<List<Map<String, Object>>>() {
}.getType());
for (Map<String, Object> item : list) {
System.out.println(item);
}
}
}
Output
{a=1, b=2}
{c=3, d=4}
No comments:
Post a Comment