一、背景最近遇到一个错误,就是某个字段肯定是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
二、上代码@Test(expected = ClassCastException.class) Map<String, Object> data = new HashMap<>(2); Assert.assertEquals(idValue, (Long) data.get(id)); String jsonString = JSON.toJSONString(data); 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对象的时候,需要实体实现序列化。工具这样设计肯定有理由的。”估计大家知道啥理由了吧。 public class JDKSerializeUtil { public static byte[] serialize(Object object) { ObjectOutputStream objectOutputStream = null; ByteArrayOutputStream byteArrayOutputStream = null; byteArrayOutputStream = new ByteArrayOutputStream(); objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); objectOutputStream.writeObject(object); return byteArrayOutputStream.toByteArray(); } catch (IOException e) { public static Object deserialization(byte[] binaryByte) { ObjectInputStream objectInputStream = null; ByteArrayInputStream byteArrayInputStream = null; byteArrayInputStream = new ByteArrayInputStream(binaryByte); objectInputStream = new ObjectInputStream(byteArrayInputStream); return objectInputStream.readObject();
public class JDKSerializeUtilTest { private Map<String, Object> map = new HashMap<>(); public void serialize() { 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进行映射 Map<String, Object> data = new HashMap<>(2); Long idLong = (Long) data.get(id); System.out.println("idLong" + idLong); String jsonString = JSON.toJSONString(data); Map map = JSON.parseObject(jsonString, Map.class); 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);
如果属性不一致用JSONField注解去映射。 3.3 避免使用通用的对象类型,如果必须用则一定考虑这个细节,坑坑坑!! 四、思考总之开发中尽量不要乱用一些对象属性转换工具,导致属性漏掉或者转错。 不要滥用Map或者JSONObject来传递参数。 如果是含Object类型JSON序列化要特别小心上述问题!!
|