美文网首页
gson 将整型数据主动转成浮点型数据bug解决方案

gson 将整型数据主动转成浮点型数据bug解决方案

作者: gooddaytoyou | 来源:发表于2020-06-19 16:48 被阅读0次

    描述

    通过google的gson 将json String串转成 Map时,里面如果有Long或Int类型会被转成浮点型。

    原始数据

    {"Param":{"stringtype":"This is String","timestamp":1597817205000,"arr":[12334,2323,334344],"double":7.0},"Type":"/api/test/getName"}
    

    代码

    String json = "{\"Param\":{\"stringtype\":\"This is String\",\"timestamp\":1597817205000,\"arr\":[12334,2323,334344],\"double\":7.0},\"Type\":\"/api/test/getName\"}";
        
    Gson gson = new Gson();
    
    Map<String, Object> objectMap = gson.fromJson(json, new TypeToken<Map<String, Object>>() {
        }.getType());
    
    System.out.println(objectMap);
    

    运行结果

    {Param={stringtype=This is String, timestamp=1.597817205E12, arr=[12334.0, 2323.0, 334344.0], double=7.0}, Type=/api/test/getName}
    

    我们可以看到timestamp=1.597817205E12, arr=[12334.0, 2323.0, 334344.0]数据格式变了。

    为什么会出现整型数据被转成浮点型数据?

    我们结合网上的提示及原码,定位到了ObjectTypeAdapter。

    ObjectTypeAdapter#read(JsonReader in)
                        ...
                        //这里,所有的NUMBER都当成Double来处理
                         case NUMBER:
                            return in.nextDouble();
                        ....
    
    

    解决方案

    方案一 重写ObjectTypeAdapter
    CustomizedObjectTypeAdapter#read(JsonReader in)
                        ...
        
                         case NUMBER:
                           //return in.nextDouble();
                            String n = in.nextString();
                            if (n.indexOf('.') != -1) {
                                return Double.parseDouble(n);
                            }
                            return Long.parseLong(n);
                        ....`
    
    

    自定义的CustomizedObjectTypeAdapter类

    class CustomizedObjectTypeAdapter extends TypeAdapter<Object> {
    
        private final TypeAdapter<Object> 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<Object> list = new ArrayList<Object>();
                    in.beginArray();
                    while (in.hasNext()) {
                        list.add(read(in));
                    }
                    in.endArray();
                    return list;
    
                case BEGIN_OBJECT:
                    Map<String, Object> map = new LinkedTreeMap<String, Object>();
                    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();
            }
        }
    }
    

    调用

    String json = "{\"Param\":{\"stringtype\":\"This is String\",\"timestamp\":1597817205000,\"arr\":[12334,2323,334344],\"double\":7.0},\"Type\":\"/api/test/getName\"}";
    GsonBuilder gsonBuilder = new GsonBuilder();
    gsonBuilder.registerTypeAdapter(new TypeToken<Map<String, Object>>() {
            }.getType(), new CustomizedObjectTypeAdapter());
    Gson gson = gsonBuilder.create();
    
    Map<String, Object> objectMap = gson.fromJson(json, new TypeToken<Map<String, Object>>() {
            }.getType());
    
    System.out.println(objectMap);
    

    运行结果

    {Param={stringtype=This is String, timestamp=1597817205000, arr=[12334, 2323, 334344], double=7.0}, Type=/api/test/getName}
    

    可以看到整型数据保持不变。

    方案二 使用Jackson

    如果你使用jackson框架来解析json,上面的问题就不存在。
    相关调用

    String json = "{\"Param\":{\"stringtype\":\"This is String\",\"timestamp\":1597817205000,\"arr\":[12334,2323,334344],\"double\":7.0},\"Type\":\"/api/test/getName\"}";
    
    TypeReference<Map<String, Object>> typeRef
                    = new TypeReference<Map<String, Object>>() {};
    ObjectMapper mapper = new ObjectMapper();
    Map<String, Object> objectMap = null;
    try {
        objectMap = mapper.readValue(json, typeRef);
    } catch (JsonProcessingException e) {
        e.printStackTrace();
    }
    
    System.out.println(objectMap);
    

    运行结果

    {Param={stringtype=This is String, timestamp=1597817205000, arr=[12334, 2323, 334344], double=7.0}, Type=/api/test/getName}
    

    相关参考

    how-can-i-prevent-gson-from-converting-integers-to-doubles

    相关文章

      网友评论

          本文标题:gson 将整型数据主动转成浮点型数据bug解决方案

          本文链接:https://www.haomeiwen.com/subject/xpqbxktx.html