JAVA的JSON序列化和二进制序列化优缺点对比

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文件被修改导致二进制反序列化的执行存在问题。

参考文章

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
假设我们有以下Java类: ```java public class Person { private int age; private String name; private boolean isMale; public Person(int age, String name, boolean isMale) { this.age = age; this.name = name; this.isMale = isMale; } // getters and setters ... } ``` 我们可以使用jcestruct库来将该类的实例序列化二进制数据。下面是一个示例: ```java import com.googlecode.protobuf.format.JsonFormat; import com.qq.tars.common.util.HexUtil; import com.qq.tars.protocol.jce.JceOutputStream; import com.qq.tars.protocol.util.TarsHelper; import java.io.ByteArrayOutputStream; import java.io.IOException; public class JceStructExample { public static void main(String[] args) throws IOException { Person person = new Person(25, "John Doe", true); // 创建JceOutputStream对象并写入数据 JceOutputStream jceOut = new JceOutputStream(); jceOut.write(person, 0); // 将JceOutputStream对象中的数据转换为byte数组 byte[] bytes = jceOut.toByteArray(); // 打印byte数组的十六进制表示 System.out.println("Serialized data: " + HexUtil.bytes2HexStr(bytes)); } } ``` 运行上面的代码会输出以下结果: ``` Serialized data: 0a 08 4a 6f 68 6e 20 44 6f 65 10 19 18 01 ``` 其中,每一对相邻的两个字符表示一个字节,因此,该序列化数据一共有14个字节。我们可以看到,它的结构如下: ``` 0a // tag = 1,表示Person对象的开始 08 // 长度为8,表示下面的数据有8个字节 4a 6f 68 6e 20 44 6f 65 // 字符串"John Doe"的UTF-8编码 10 // tag = 2,表示age字段 19 // 长度为1,表示下面的数据有1个字节 18 // age字段的值,25的JCE编码 01 // tag = 3,表示isMale字段,布尔类型 ``` 这就是一个简单的jcestruct序列化的例子。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值