JSON序列化导致Long类型被搞成Integer经 4000 典巨坑
一、背景
最近遇到一个错误,就是某个字段肯定是Long类型的,通过Map<String,Object>方式转成JSON字符串,然后存到了DB的某个字段里。
为了Json存储字,然后反序列化为Map(不是自定义的常规对象)
比如某二方为了提供通用的接口能力,将Map<String,Object>的数据通过JSON序列化方式缓存然后JSON反序列化拿到Map。
等情况。
用的时候就通过Key获取对象之后直接强转Long,然后类型转换异常。
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Long
二、上代码
[code] @Test(expected = ClassCastException.class) public void testJson() { String id = "id"; String name = "name"; Long idValue = 3000L; Map<String, Object> data = new HashMap<>(2); data.put(id, idValue); data.put(name, "张三"); Assert.assertEquals(idValue, (Long) data.get(id)); String jsonString = JSON.toJSONString(data); // 反序列化时Long被转为了Integer Map map = JSON.parseObject(jsonString, Map.class); Object idObj = map.get(id); Assert.assertTrue(idObj instanceof Integer); Assert.assertEquals(idValue, (Long) idObj); }
没用通过JSON序列化,虽然类型为Object,但是实际的类型为Long。
序列化为Json时后,Josn串是没有 Long类型的,而且反转回来也是Object接收,如果数字小于Interger的最大值,给转成了Integer!
三、方案
3.1 采用JDK自带的序列化。
https://blog.csdn.net/outsanding/article/details/80963646 提到“redis工具,在存java对象的时候,需要实体实现序列化。工具这样设计肯定有理由的。”估计大家知道啥理由了吧。
[code]public class JDKSerializeUtil { public static byte[] serialize(Object object) { ObjectOutputStream objectOutputStream = null; ByteArrayOutputStream byteArrayOutputStream = null; try { byteArrayOutputStream = new ByteArrayOutputStream(); objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); objectOutputStream.writeObject(object); return byteArrayOutputStream.toByteArray(); } catch (IOException e) { e.printStackTrace(); } return null; } public static Object deserialization(byte[] binaryByte) { ObjectInputStream objectInputStream = null; ByteArrayInputStream byteArrayInputStream = null; byteArrayInputStream = new ByteArrayInputStream(binaryByte); try { objectInputStream = new ObjectInputStream(byteArrayInputStream); return objectInputStream.readObject(); } catch (Exception e) { e.printStackTrace(); } return null; } }
[code]public class JDKSerializeUtilTest { private Map<String, Object> map = new HashMap<>(); @Before public void init() { map.put("id", 200L); map.put("name", "张三"); } @Test public void serialize() { } @Test public void unserizlize() { byte[] serialize = JDKSerializationUtil.serialize(map); Object deserialize = JDKSerializationUtil.deserialization(serialize); Map<String, Object> map = (Map<String, Object>) deserialize; Object id = map.get("id"); Assert.assertEquals(java.lang.Long.class, id.getClass()); } }
3.2 采用JSON反序列化Map进行映射
[code] @Test public void testJson() { String id = "id"; String name = "name"; Map<String, Object> data = new HashMap<>(2); data.put(id, 3000L); data.put(name, "张三"); Long idLong = (Long) data.get(id); System.out.println("idLong" + idLong); String jsonString = JSON.toJSONString(data); // 反序列化时Long被转为了Integer Map map = JSON.parseObject(jsonString, Map.class); // 直接用JSON转没问题 User user = new JSONObject(map).toJavaObject(User.class); System.out.println(user); //强转不行 Object idObj = map.get(id); System.out.println(idObj.getClass()); Long idLong2 = (Long) idObj; System.out.println("idLong2" + idLong2); }
[code]@Data public class User { private Long id; private String name; }
如果属性不一致用JSONField注解去映射。
3.3 避免使用通用的对象类型,如果必须用则一定考虑这个细节,坑坑坑!!
四、思考
总之开发中尽量不要乱用一些对象属性转换工具,导致属性漏掉或者转错。
不要滥用Map或者JSONObject来传递参数。
如果是含Object类型JSON序列化要特别小心上述问题!!
如果觉得本文对你有帮助,欢迎点赞,欢迎关注我,如果有补充欢迎评论交流,我将努力创作更多更好的文章。
另外欢迎加入我的知识星球,知识星球ID:15165241 一起交流学习。
https://t.zsxq.com/Z3bAiea 申请时标注来自CSDN。
- 关于数据序列化(5),定制FastJSON序列化(解决Java大Long类型js的Number接收丢失数据的问题,不序列化某些属性)
- JSON 序列化与弱类型
- 【CCS仿真】如何将CCS仿真时memory中的数据以Hex、Integer、 Long 、Float、 Addressable Unit类型保存到PC
- springMVC中返回json时,日期类型自动转换为long类型的时间戳的处理方案(一个配置解决)
- JavaScriptSerializer 对 DateTime 数据类型的JSON序列化的问题
- 解决Java中Long类型转换成Json时,在Js代码调用时精度丢失的问题
- json-lib反序列化时(JSONObject.toBean),时间类型为空的处理
- Hibernate 3.2 SQL函数返回类型从Integer变为Long
- 记录一次SpringBoot 2.x Redis 序列化Integer类型不起作用
- 后台date类型转换为json字符串时,返回前台页面的是long类型的时间戳问题解决
- datasnap 2010 利用JSON序列化和反序列化任何类型的对象
- 用js解析经json序列化后的C#的DateTime类型数据
- (php的弱类型导致的小问题)某变量可能是数字或非数字(对象、字符串、json等)时,应该如何去判断
- 用js解析经json序列化后的C#的DateTime类型数据
- mybatis中格式为DateTime或者Date,json格式会转成long类型的解决方案
- fastJson如何序列化一个包含list对象的Map对象,如Map<String,List<T>>类型的对象
- JavaScriptSerializer 对 DateTime 数据类型的JSON序列化的问题
- Java中int(Integer)类型与long(Long)类型数据的相互转化
- (php的弱类型导致的小问题)某变量可能是数字或非数字(对象、字符串、json等)时,应该如何去判断
- C# Json反序列化 数据协定类型 无法反序列化 因为未找到必需的数据成员