• 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
  • 相关阅读:
    企业架构LNMP学习笔记16
    十年开发老手,深度解析企业用人标准为何越来越高?!
    查找文本文件的差集
    代码中可能会使用
    相控阵雷达天线不同阵列的特性matlab仿真分析——有限扫描阵,稀疏阵,多波束阵,共形阵
    掩码,反掩码与通配符掩码
    Rabbitmq 的管理配置
    Web前端接入Microsoft Azure AI文本翻译
    浅谈红黑树
    【线性代数】行列式和矩阵
  • 原文地址:https://blog.csdn.net/Urbanears/article/details/127863240