我的json中有整数,我不希望gson将它们转换成双打.以下不起作用:
@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}
有没有办法在我的地图中使用整数而不是双打?
{id=1, quantity=2, name=apple} {id=3, quantity=4, name=orange}
编辑:并非所有字段都是整数.我相应地修改了我的例子.
我在网上看了很多例子,包括这个网站上的一些答案,但在这个特殊情况下它不起作用.
1)您必须在您的问题中创建自定义JsonDeserializer而不是JsonSerializer.
2)我不认为这种行为来自Double deserializer.它更像是json对象/地图问题
这是从 source code :
case NUMBER: return in.nextDouble();
因此,您可以尝试使用Map<String,Object>的自定义反序列化器. (或者如果你想要一些更通用的地图):
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; } }
要使用它,您必须为registerTypeAdapter和gson.fromJson函数提供正确的TypeToken:
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>>创建自定义对象.更酷,更容易阅读的方式
翻译自:https://stackoverflow.com/questions/36508323/how-can-i-prevent-gson-from-converting-integers-to-doubles