JAVA的JSON序列化和二进制序列化
一、前言
最近在一个项目中因为序列化不一致问题出现了项目的卡壳。问题出现在一个后端组员修改了一个后端共享序列化类,但是测试后没有及时提交这块代码,导致其他开发成员在发序列化对象时,出现了序列化异常。
但是在开发的时候也出现过修改bean,但是没有出现过序列化异常的问题。于是经过对比后发现出现异常的bean使用二进制序列化,无异常出现的bean使用json二进制序列化
。
于是决定写一个粗劣的对比。但是推荐看看本文章的参考文章,可以学习到很多的二进制反序列化的知识点。
二、对比
1. 环境
- JSON序列化工具:fastjson
- 二进制序列化工具:SerializationUtils(spring uitls 提供)
- Bean对象
@Getter
@AllArgsConstructor
@ToString
public class BinaryBean implements Serializable {
private Integer num;
private String string;
private BinaryBean value;
}
@Getter
@AllArgsConstructor
@ToString
public class JsonBean {
private Integer num;
private String string;
private JsonBean value;
}
- 测试体
public static void main(String[] args) {
// 1. 二进制
BinaryBean binaryValue = new BinaryBean(2, "内部", null);
BinaryBean binaryBean = new BinaryBean(1, "外部", binaryValue);
byte[] binaryBytes = SerializationUtils.serialize(binaryBean);
BinaryBean binaryBean2 = (BinaryBean) SerializationUtils.deserialize(binaryBytes);
System.out.println(binaryBean2);
// 2. JSON
JsonBean jsonValue = new JsonBean(2, "内部", null);
JsonBean jsonBean = new JsonBean(1, "外部", jsonValue);
byte[] jsonBytes = JSON.toJSONString(jsonBean, SerializerFeature.WriteClassName).getBytes(StandardCharsets.UTF_8);
JsonBean jsonBean2 = JSON.parseObject(new String(jsonBytes, StandardCharsets.UTF_8), JsonBean.class);
System.out.println(jsonBean2);
}
2. 对比
通过上述的使用我们会发现,json的序列化使用和二进制的序列化使用上大致上没有什么差别。基本的区别为:
- 二进制bean需要实现二进制接口
Serializable
,而JSON bean并不需要。 - JSON和二进制反序列化的实质方式不同。JSON因为存在键值对,在JAVA内部可以通过类似反射的方式执行属性匹配和实体创建;二进制反序列化的数据结构可以理解一种JAVA对象生成操作集合,JAVA通过读取这二进制流,并进行执行(个人理解)。
当然通过第二点区别,我们可以总结出更多的不同点,比如:
- 平台差异性。JAVA二进制只能对于JDK版本才能使用,JSON可以跨平台。因为JSON是数据格式,而二进制可以理解为操作日志。
- 反序列化容错性。JSON反序列化,如果出现filed不存在或是修改,最差是生成的实体类的没有该字段的值,而二级制反序列化的设置就无法执行。
- 阅读性与保密性。JSON阅读性高,二进制阅读性小。当然保密性和阅读性刚好是相反的。
三、结尾
再说回项目出现的问题,问题很大情况下就存在因CLASS文件被修改导致二进制反序列化的执行存在问题。