如何解决JSON反序列化Long变Integer或Double的问题


这篇文章主要为大家展示了“如何解决JSON反序列化Long变Integer或Double的问题”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“如何解决JSON反序列化Long变Integer或Double的问题”这篇文章吧。工作中可能会遇到对 Map 进行 JSON 序列化,其中值中包含 Long 类型的数据,反序列化后强转 Long 时报类型转换异常的问题。本文简单探讨下该问题,并给出解决方案,如果你想直接看建议,直接翻到第三部分即可。本文主要以 jackson、 gson、fastjson 三个库为例,版本分别如下:代码示例运行结果:{“aInteger”:1,”aLong”:2}
— fastjson —–
key:aLong,value=2,valueClass=class java.lang.Integer
key:aInteger,value=1,valueClass=class java.lang.Integer
— gson —–
key:aInteger,value=1.0,valueClass=class java.lang.Double
key:aLong,value=2.0,valueClass=class java.lang.Double
— jackson —–
key:aInteger,value=1,valueClass=class java.lang.Integer
key:aLong,value=2,valueClass=class java.lang.IntegeraLong 虽然原始类型为 Long 但是 fastjson 和 jackson 中被反序列化为 Integer 类型,gson 中被映射为 Double 类型。我们观察序列化后的 json 字符串:会发现其实 JSON 中并没有包含类型信息,而反序列化的类型为 Map.class 或者 Map 类型,当你只知道这些信息时,你无法得知 aLong 原始类型为 Long 。因此不同的JSON 序列化工具给出了自己的默认处理行为。当我们把 aLong 的值调整到 超过 (Integer.MAX_VALUE,Long.MAX_VALUE] 的范围之间时,fastjson 和 jackson 可以解析为 Long 类型。输出的结果:{“aInteger”:1,”aLong”:9223372036854775807}
— fastjson —–
key:aLong,value=9223372036854775807,valueClass=class java.lang.Long
key:aInteger,value=1,valueClass=class java.lang.Integer
— gson —–
key:aInteger,value=1.0,valueClass=class java.lang.Double
key:aLong,value=9.223372036854776E18,valueClass=class java.lang.Double
— jackson —–
key:aInteger,value=1,valueClass=class java.lang.Integer
key:aLong,value=9223372036854775807,valueClass=class java.lang.Long我们大致了解到, fastjson 和 jackson 默认情况下整数类型优先选取 Integer ,超过 Integer 范围再选择 Long ,以此类推。而当我们放入 Float 类型时,结果又有差异:运行结果:{“aInteger”:1,”aFLoat”:0.1}
— fastjson —–
key:aInteger,value=1,valueClass=class java.lang.Integer
key:aFLoat,value=0.1,valueClass=class java.math.BigDecimal
— gson —–
key:aInteger,value=1.0,valueClass=class java.lang.Double
key:aFLoat,value=0.1,valueClass=class java.lang.Double
— jackson —–
key:aInteger,value=1,valueClass=class java.lang.Integer
key:aFLoat,value=0.1,valueClass=class java.lang.Doublefastjson 中 Float 被解析为 BigDecimal, gson 和 jackson 中被解析为 Double 类型。具体底层如何处理,大家可以对每个框架的反序列方法单步跟进去即可得到答案。这里以 fastjson 为例,简单调试下:fastjson 底通过 com.alibaba.fastjson.parser.ParserConfig#getDeserializer 方法获取当前类型的反序列化器为 MapDeserializer执行其反序列化方法:通过 com.alibaba.fastjson.parser.deserializer.MapDeserializer#parseMap 对 Map 类型进行解析。由于 Map的 valueType 类型为 Object,因此对 aFloat 使用 JavaObjectDeserializer 反序列化器进行解析。跟进 lexer.decimalValue 看下:最终通过 com.alibaba.fastjson.parser.JSONScanner#decimalValue 将 aFloat 解析为 BigDecimal 类型。如果我们能将原始类型写入到 JSON 字符串中,那么反序列化时自然就可以复原原始的类型。在 fastjson 中可以使用 SerializerFeature.WriteClassName打印的结果{“@type”:”java.util.HashMap”,”aFloat”:3.0F,”aInteger”:1,”aLong”:2L}
— fastjson —–
key:aLong,value=2,valueClass=class java.lang.Long
key:aFloat,value=3.0,valueClass=class java.lang.Float
key:aInteger,value=1,valueClass=class java.lang.Integer虽然,这种方法可以解决问题,但是这也通常要求序列化和反序列化使用同一个 JSON 工具。比如上面的 {“@type”:”java.util.HashMap”,”aFloat”:3.0F,”aInteger”:1,”aLong”:2L} 直接使用 jackson 进行反序列化会报错:报错内容:— jackson —–
Exception in thread “main” c免费云主机域名om.fasterxml.jackson.core.JsonParseException: Unexpected character (‘F’ (code 70)): was expecting comma to separate Object entries
at [Source: (String)”{“@type”:”java.util.HashMap”,”aFloat”:3.0F,”aInteger”:1,”aLong”:2L}”; line: 1, column: 43]
at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:2391)
at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:735)
at com.fasterxml.jackson.core.base.ParserMinimalBase._reportUnexpectedChar(ParserMinimalBase.java:659)强烈建议不要怕麻烦,直接定义 POJO 类。不仅不受 JSON 框架的约束,而且对方解析时也非常明确,不容易出错。如工作中在发送MQ 消息时很多人图方便,不想定义POJO 对象,因为这样通常需要打包比较麻烦,就将要传输给其他系统的数据定义为 Map 类型,下游再根据 key 去解析,这是一个非常不好的习惯。很容易造成上下游类型不一致,造成更换 JSON 反序列化工具时出现故障。因此发送 MQ 消息时,最好给出相应的 POJO 类。实际工作中,还遇到有同学将 Map 使用 JSON 序列化的方式存储到 Redis 中,然后反序列化后,将原本 Long 类型的值,强转为 Long 导致线上出现BUG(前面讲到,这种情况下使用 fastjson 时,如果值小于整数最大值,反序列化为 Integer 类型,强转必然会报错)。如果上游序列化是 Map, 如果类型核实清楚,我们依然可以自定义 POJO 类来反序列化。输出结果:Data(aFloat=0.1, aInteger=1)可能有些同学会觉得定义 POJO 类很麻烦,其实我们可以使用 IDEA 插件或者在线工具实现 JSON 字符串生成 POJO 类。如 Json2Pojo IDEA 插件和一些在线生成工具:https://json2csharp.com/json-to-pojohttps://www.javainuse.com/pojo以上是“如何解决JSON反序列化Long变Integer或Double的问题”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注百云主机行业资讯频道!

相关推荐: SpringBoot +DynamicDataSource如何切换多数据源

小编给大家分享一下SpringBoot+DynamicDataSource如何切换多数据源,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧免费云主机域名!刚开始用一个数据源,但是上头要求…

免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。

(0)
打赏 微信扫一扫 微信扫一扫
上一篇 10/01 19:31
下一篇 10/01 19:31

相关推荐