How can I prevent gson from converting integers to doubles

前端 未结 6 674
再見小時候
再見小時候 2020-12-05 07:37

I\'ve got integers in my json, and I do not want gson to convert them to doubles. The following does not work:

@Test
public void keepsIntsAsIs(){
    String          


        
6条回答
  •  感动是毒
    2020-12-05 08:11

    Streaming version of @varren's answer:

    class CustomizedObjectTypeAdapter extends TypeAdapter {
    
        private final TypeAdapter delegate = new Gson().getAdapter(Object.class);
    
        @Override
        public void write(JsonWriter out, Object value) throws IOException {
            delegate.write(out, value);
        }
    
        @Override
        public Object read(JsonReader in) throws IOException {
            JsonToken token = in.peek();
            switch (token) {
                case BEGIN_ARRAY:
                    List list = new ArrayList();
                    in.beginArray();
                    while (in.hasNext()) {
                        list.add(read(in));
                    }
                    in.endArray();
                    return list;
    
                case BEGIN_OBJECT:
                    Map map = new LinkedTreeMap();
                    in.beginObject();
                    while (in.hasNext()) {
                        map.put(in.nextName(), read(in));
                    }
                    in.endObject();
                    return map;
    
                case STRING:
                    return in.nextString();
    
                case NUMBER:
                    //return in.nextDouble();
                    String n = in.nextString();
                    if (n.indexOf('.') != -1) {
                        return Double.parseDouble(n);
                    }
                    return Long.parseLong(n);
    
                case BOOLEAN:
                    return in.nextBoolean();
    
                case NULL:
                    in.nextNull();
                    return null;
    
                default:
                    throw new IllegalStateException();
            }
        }
    }
    
    
    

    It is modified version of ObjectTypeAdapter.java. These original lines:

    case NUMBER:
        return in.nextDouble();
    

    are replaced by this:

    case NUMBER:
        String n = in.nextString();
        if (n.indexOf('.') != -1) {
            return Double.parseDouble(n);
        }
        return Long.parseLong(n);
    

    In this code, number is read as string and number's type is selected based on existence of dot: number is double only if it has a dot in its string representation and it is long otherwise. Such solution preserves original values of source JSON.

    This modified adapter could be used as universal if you could register it for Object type but Gson prevents it:

    // built-in type adapters that cannot be overridden
    factories.add(TypeAdapters.JSON_ELEMENT_FACTORY);
    factories.add(ObjectTypeAdapter.FACTORY);
    

    You have to register this type adapter to those types that you need, e.g. Map and List:

    CustomizedObjectTypeAdapter adapter = new CustomizedObjectTypeAdapter();
    Gson gson = new GsonBuilder()
            .registerTypeAdapter(Map.class, adapter)
            .registerTypeAdapter(List.class, adapter)
            .create();
    

    Now Gson can deserialize numbers as is.

    提交回复
    热议问题