前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JSON序列化导致Long类型被搞成Integer经典巨坑

JSON序列化导致Long类型被搞成Integer经典巨坑

作者头像
明明如月学长
发布2021-08-31 15:38:50
1.3K0
发布2021-08-31 15:38:50
举报
文章被收录于专栏:明明如月的技术专栏

一、背景

最近遇到一个错误,就是某个字段肯定是Long类型的,通过Map方式转成JSON字符串,然后存到了DB的某个字段里。

为了Json存储字,然后反序列化为Map(不是自定义的常规对象)

比如某二方为了提供通用的接口能力,将Map的数据通过JSON序列化方式缓存然后JSON反序列化拿到Map。

等情况。

用的时候就通过Key获取对象之后直接强转Long,然后类型转换异常。

java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Long

二、上代码

代码语言:javascript
复制
    @Test(expected = ClassCastException.class)
    public void testJson() {
        String id = "id";
        String name = "name";
        Long idValue = 3000L;
        Map 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对象的时候,需要实体实现序列化。工具这样设计肯定有理由的。”估计大家知道啥理由了吧。

代码语言:javascript
复制
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;
    }

}
代码语言:javascript
复制
public class JDKSerializeUtilTest {

    private Map 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 map = (Map) deserialize;
        Object id = map.get("id");
        Assert.assertEquals(java.lang.Long.class, id.getClass());
    }
}

3.2 避免使用通用的对象类型

自定义一个强类型的对象来传递数据。

3.3 使用JSON自带的转换工具

代码语言:javascript
复制
@Data
public class User {
    private Long id;

    private String name;
}
代码语言:javascript
复制
   @Test
    public void testJson2() {
        String id = "id";
        String name = "name";
        Long idValue = 3000L;
        Map 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);

        // 转换成 User时 Integer 转为了Long
        User user = JSON.toJavaObject(new JSONObject(map), User.class);
        System.out.println(user);
    }

3.4 手动转换

手动将 Map 转为目标对象,此时注意 Long 可能降级为 Integer,特殊处理即可。

四、思考

总之开发中尽量不要乱用一些对象属性转换工具,导致属性漏掉或者转错。

不要滥用Map或者JSONObject来传递参数。

如果是含Object类型JSON序列化要特别小心上述问题!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/06/05 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、背景
  • 二、上代码
  • 三、方案
  • 四、思考
相关产品与服务
文件存储
文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档