我的 json 中有整数,我不希望 gson 将它们转换为 double 。以下不起作用:
@Test
public void keepsIntsAsIs(){
String json="[{\"id\":1,\"quantity\":2,\"name\":\"apple\"},{\"id\":3,\"quantity\":4,\"name\":\"orange\"}]";
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Double.class, new DoubleSerializerAsInt());
Gson gson = gsonBuilder.create();
List<Map<String, Object>> l = gson.fromJson(json, List.class);
for(Map<String, Object> item : l){
System.out.println(item);
}
}
private static class DoubleSerializerAsInt implements JsonSerializer<Double>{
@Override
public JsonElement serialize(Double aDouble, Type type, JsonSerializationContext jsonSerializationContext) {
int value = (int)Math.round(aDouble);
return new JsonPrimitive(value);
}
}
输出不是我想要的:
{id=1.0, quantity=2.0, name=apple}
{id=3.0, quantity=4.0, name=orange}
有没有办法在我的 map 中使用整数而不是 double 值?
{id=1, quantity=2, name=apple}
{id=3, quantity=4, name=orange}
编辑:并非我的所有字段都是整数。我已经相应地修改了我的示例。 我已经在线阅读了很多示例,包括本网站上的一些答案,但在这种特殊情况下不起作用。
最佳答案
1) 您必须创建自定义 JsonDeserializer
而不是 JsonSerializer
就像你的问题一样。
2) 我不认为这种行为来自 Double
反序列化器。它更像是 json 对象/ map 问题
这里来自source code :
case NUMBER:
return in.nextDouble();
因此您可以尝试使用自定义反序列化器来处理 Map<String, Object>
(或者如果你愿意,可以使用一些更通用的 map ):
public static class MapDeserializerDoubleAsIntFix 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 in) {
if(in.isJsonArray()){
List<Object> list = new ArrayList<Object>();
JsonArray arr = in.getAsJsonArray();
for (JsonElement anArr : arr) {
list.add(read(anArr));
}
return list;
}else if(in.isJsonObject()){
Map<String, Object> map = new LinkedTreeMap<String, Object>();
JsonObject obj = in.getAsJsonObject();
Set<Map.Entry<String, JsonElement>> entitySet = obj.entrySet();
for(Map.Entry<String, JsonElement> entry: entitySet){
map.put(entry.getKey(), read(entry.getValue()));
}
return map;
}else if( in.isJsonPrimitive()){
JsonPrimitive prim = in.getAsJsonPrimitive();
if(prim.isBoolean()){
return prim.getAsBoolean();
}else if(prim.isString()){
return prim.getAsString();
}else if(prim.isNumber()){
Number num = prim.getAsNumber();
// here you can handle double int/long values
// and return any type you want
// this solution will transform 3.0 float to long values
if(Math.ceil(num.doubleValue()) == num.longValue())
return num.longValue();
else{
return num.doubleValue();
}
}
}
return null;
}
}
要使用它,您必须提供适当的 TypeToken
至 registerTypeAdapter
和 gson.fromJson
功能:
String json="[{\"id\":1,\"quantity\":2,\"name\":\"apple\"}, {\"id\":3,\"quantity\":4,\"name\":\"orange\"}]";
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(new TypeToken<Map <String, Object>>(){}.getType(), new MapDeserializerDoubleAsIntFix());
Gson gson = gsonBuilder.create();
List<Map<String, Object>> l = gson.fromJson(json, new TypeToken<List<Map<String, Object>>>(){}.getType() );
for(Map<String, Object> item : l)
System.out.println(item);
String serialized = gson.toJson(l);
System.out.println(serialized);
结果:
{id=1, quantity=2, name=apple}
{id=3, quantity=4, name=orange}
Serialized back to: [{"id":1,"quantity":2,"name":"apple"},{"id":3,"quantity":4,"name":"orange"}]
PS:这只是您可以尝试的另一种选择。就我个人而言,我想为您的 json 创建自定义对象而不是 List<Map<String, Integer>>
更酷更容易阅读的方式
关于java - 如何防止 gson 将整数转换为 double ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36508323/