• GSON转换成Long型变为科学计数法及时间格式转换异常的解决方案


    GSON踩坑:对象转换成Map时,Long型变为科学计数法及时间格式转换异常的解决方案

    问题场景

    在我需要将一个对象转为Map类型时,调用Gson.fromJson发现,原来对象中的long类型的timestamp字段,被解析成了科学计数法,导致后续的解析出错。

    下面给出测试代码进行演示

    首先定义一个pojo类,包含一个long类型的timestamp字段

    import lombok.Data;
    import lombok.ToString;
    
    @Data
    @ToString
    public class ResultItem {
    
        private long timestamp;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    Gson代码

    public class JSONUtils {
        private static final Gson GSON = new GsonBuilder()
                .setLongSerializationPolicy(LongSerializationPolicy.DEFAULT)
                .serializeNulls().create();
    
        public static Map toMap(String s) {
    
            if (StringUtils.isEmpty(s)) {
                return null;
            }
            return GSON.fromJson(s, Map.class);
        }
    
        public static Map<String, Object> convert(Object o) {
            Type type = new TypeToken<Map<String, Object>>() {
            }.getType();
            return GSON.fromJson(JSONUtils.toString(o), type);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    测试代码

        @Test
        public void testGson(){
           long timestamp = 1668394335647l;
            ResultItem item = new ResultItem();
            item.setTimestamp(timestamp);
    
            Map<String, Object> convert = JSONUtils.convert(item);
            System.out.println(convert);
    
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    结果如下:

    {timestamp=1.668394335647E12}
    
    • 1

    可以发现,ResultItem类对象在调用Gson.fromJson后,Map中的timestamp字段被转成了科学计数法来表示。

    解决办法

    一、修改GSON的配置

    修改GSON的配置,将setLongSerializationPolicy(LongSerializationPolicy.DEFAULT)改为setLongSerializationPolicy(LongSerializationPolicy.STRING)。如下所示:

    public class JSONUtils {
        private static final Gson GSON = new GsonBuilder()
                .setLongSerializationPolicy(LongSerializationPolicy.STRING)	# 将DEFAULT改为STRING
                .serializeNulls().create();
    
        public static Map toMap(String s) {
    
            if (StringUtils.isEmpty(s)) {
                return null;
            }
            return GSON.fromJson(s, Map.class);
        }
    
        public static Map<String, Object> convert(Object o) {
            Type type = new TypeToken<Map<String, Object>>() {
            }.getType();
            return GSON.fromJson(JSONUtils.toString(o), type);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    再次测试结果:

    {timestamp=1668394335647}
    
    • 1

    可以看到,得到的Map中的timestamp字段保留了原来long的格式,不再是被解析成科学计数法,解决了问题。

    二、换成FastJson进行解析

    第二种方法是,换一种第三方解析工具,将Google的Gson换成Alibaba的FastJson工具进行解析,代码如下:

    修改convert方法为FastJson工具进行解析

    public class JSONUtils {
        private static final Gson GSON = new GsonBuilder()
                .setLongSerializationPolicy(LongSerializationPolicy.DEFAULT)
                .serializeNulls().create();
    
        public static Map toMap(String s) {
    
            if (StringUtils.isEmpty(s)) {
                return null;
            }
            return GSON.fromJson(s, Map.class);
        }
    
        public static Map<String, Object> convert(Object o) {
            Type type = new TypeToken<Map<String, Object>>() {
            }.getType();
            return JSONObject.parseObject(JSON.toJSONString(o), type);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    再次测试结果:

    {timestamp=1668394335647}
    
    • 1

    可以看到结果仍然保留了原先long格式的数据,同样解决了问题。

    时间格式转换异常

    对于时间格式的转换异常,可以修改Gson的配置如下:

    public class JSONUtils {
        private static final Gson GSON = new GsonBuilder()
            	.setDateFormat("yyyy-MM-dd HH:mm:ss")	# Gson添加DateFormat配置
                .setLongSerializationPolicy(LongSerializationPolicy.STRING)	# 将DEFAULT改为STRING
                .serializeNulls().create();
    
        public static Map toMap(String s) {
    
            if (StringUtils.isEmpty(s)) {
                return null;
            }
            return GSON.fromJson(s, Map.class);
        }
    
        public static Map<String, Object> convert(Object o) {
            Type type = new TypeToken<Map<String, Object>>() {
            }.getType();
            return GSON.fromJson(JSONUtils.toString(o), type);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
  • 相关阅读:
    LeetCode:字符串的前缀分数和
    【开源】最近写了一个简单的网址导航网站
    Lombok常用方法及原理介绍
    vmware虚拟机启动、使用ubuntu问题
    Lambda求和函数在excel上的应用
    开启婚恋新市场!!!
    微信照片过期打不开怎么办?用这个办法可找回
    LeetCode //C - 69. Sqrt(x)
    雅思 《九分达人》阅读练习(二)
    wpf中如何DataGrid中的行选择设置点击不被鼠标悬停影响
  • 原文地址:https://blog.csdn.net/Urbanears/article/details/127863240