首页 > 编程语言 >JAVA自定义对象序列化,自定义的控制每个字节的序列化情况

JAVA自定义对象序列化,自定义的控制每个字节的序列化情况

时间:2023-12-09 09:22:39浏览次数:52  
标签:JAVA 字节 自定义 private MagicField byte 序列化 order

在java中,正常来说序列化是可以直接继承Serializable,或使用类似于fastjson, protobuf等框架。
但是这些框架对于二进制协议,自定义协议,私有协议方面却不太好使,私有协议大多还是按照字节的方式组织数据,对于java来说需要控制每个属性的序列化方式,

所以这块主要还是以传统的方式,读字节流开始,按照字节读取并填充对象。

这里给大家推一个好用的框架Magic-byte, 这个可以很方便的控制字节序列化方式进而实现私有协议;

比如以下代码:

// declare class must use public
// 使用大端模式, 默认为大端
@MagicClass(byteOrder = ByteOrder.BIG_ENDIAN)
public class School {
    // 10 byte, 普通数据类型, 占用10字节长度
    @MagicField(order = 1, size = 10)
    private String name;
    // 2 byte, 长度字段, 数据序列化时将自动填充实际数据长度
    @MagicField(order = 3, calcLength = true)
    private short length;
    // 支持组合模式, 这里嵌入了 Student 对象
    // 总字节数 = students.bytes * length
    @MagicField(order = 5, size = 2)
    private Student[] students;
    // 0 byte, 注意, 此处无法序列化, 不支持的数据类型将会被忽略
    @MagicField(order = 7)
    private List<Object> notSupport;
    // 0 byte, 注意, 此处无法序列化, 不支持的数据类型将会被忽略
    @MagicField(order = 9)
    private Object age;
    // 4 byte, 注意, 此处指定为秒级时间戳, 同时指定使用4个字节保存, 未指定则默认6个字节
    @MagicField(order = 13, size = 4, timestampFormat = TimestampFormatter.TO_TIMESTAMP_SECONDS)
    private Date[] birthdays;
    // 1 byte, 普通数据类型, 通过order配置序列化顺序, 序列号顺序和定义顺序无关
    @MagicField(order = 15)
    private byte age;
    // 1 byte, 校验和字段, 序列化时如提供计算函数则将会自动填充
    @MagicField(order = 17)
    private byte checkCode;

   
    // getter and setter ...
}

@MagicClass()
public class Student {
    // 10 byte, 普通数据, 长度为 10 字节
    @MagicField(order = 1, size = 10)
    private String name;
    // 4 byte, 普通数据, 整数, 此字段决定后续 phones 字段长度
    @MagicField(order = 5)
    private int length;
    // 总字节数 = phones.size * length
    // 单个元素 8 byte, 此List并未直接指定大小, 大小由 length 字段决定. length字段数据类型只能为 byte, short, int, UNumber
    @MagicField(order = 10, dynamicSizeOf = "length")
    private List<Long> phones;
    // 1 byte
    @MagicField(order = 15)
    private byte age;
    // 生日, 这里为秒级时间戳, 指定使用4个字节, 日期类型未指定则默认6个字节
    @MagicField(order = 18, size = 4, timestampFormat = TimestampFormatter.TO_TIMESTAMP_SECONDS)
    private Date birthDay;
    // getter and setter ...
}

public class Hello {
    void main() {
        // 全局配置校验和计算函数
        MagicByte.configMagicChecker(Checker::customChecker);
        School school = new School();
        school.setAge((byte) 23);
    
        // you can set other propertis
        // object to bytes
        // 也可以单独传入计算函数
        byte[] bytes = MagicByte.unpack(school, Checker::customChecker); 
        School school2 = MagicByte.pack(bytes, School.class); // bytes to object
        System.out.println(school.getAge() == school2.getAge()); // out put true
    
    }
}

public class Checker {
    /**
     * 序列化时: data数据中包含所有已序列化的数据(包括 calcLength 也已经调用并序列化)
     * 反序列化时: data数据为传入数据的副本
     * @param data
     * @return
     */
    public static byte[] customChecker(byte[] data) {
        return new byte[]{0xff};
    }
}

上面代码是直接从开始页copy过来的,不过确实用起来很方便,安利给大家哈

maven引入,新版本大家可以去github主页看

<dependency>
  <groupId>io.github.misterchangray</groupId>
  <artifactId>magic-byte</artifactId>
  <version>2.4.1</version>
</dependency>

标签:JAVA,字节,自定义,private,MagicField,byte,序列化,order
From: https://www.cnblogs.com/raychang/p/17889470.html

相关文章

  • Elasticsearch:一个强大的Java搜索引擎
    一、介绍Elasticsearch是一个基于ApacheLucene库的开源搜索引擎,它提供了一个分布式、多租户能力的全文搜索引擎,同时具有HTTP网络界面和无模式JSON文档。Elasticsearch是用Java开发的,它是一个可扩展的系统,可以很容易地通过插件来扩展其功能。二、特点全文搜索引擎:Elasticsearch使用......
  • Java IO流(上)
    JavaIO流一、基础知识IO流即存储和读取数据的解决方案。(一)File表示系统中的文件或者文件夹的路径获取文件信息(大小,文件名,修改时间)创建文件/文件夹删除文件/文件夹判断文件的类型注意:File类只能对文件本身进行操作,不能读写文件里面存储的数据。(二)IO流用于读写文件中的数据(可以读......
  • Java 时间相减
    题目描述你是个贪睡虫,有一天被老师逮个正着,这个老师很有意思,提出一个问题:“给定入睡时刻和起床时刻,计算一共睡了多长时间”,如果回答正确就可以免于处罚。入睡时刻和起床时刻都采用24小时制表示法(见备注),而且知道睡觉时间最少为1秒,最多为24小时。输入【输入格式】输入第一行描......
  • Java之包装类的详细解析
     包装类5.1概述Java提供了两个类型系统,基本类型与引用类型,使用基本类型在于效率,然而很多情况,会创建对象使用,因为对象可以做更多的功能,如果想要我们的基本类型像对象一样操作,就可以使用基本类型对应的包装类,如下:基本类型对应的包装类(位于java.lang包中)byteByteshortShortintIntege......
  • JavaScript笔记
    JavaScript的组成:     1.数据类型:JavaScript有8种基本数据类型,包括Undefined、Null、Boolean、Number、String、BigInt、Symbol和Object。变量:在JavaScript中,可以使用var、let或const关键字声明变量。函数:JavaScript中的函数是一种可重用的代码块,可以使用fun......
  • Java-Spring框架中用到的设计模式
    Java-Spring框架中用到的设计模式单例模式(Singleton)Spring中的Bean默认是单例的,容器中只存在一个实例。这有助于节省资源,提高性能。工厂模式(Factory)Spring使用工厂模式来创建和管理Bean。通过配置文件或注解,Spring容器可以根据需要创建相应的Bean对象。代理模......
  • Java-聚簇索引和非聚簇索引
    Java-聚簇索引和非聚簇索引聚簇索引(ClusteredIndex)和非聚簇索引(Non-clusteredIndex)是数据库中两种不同的索引结构。聚簇索引(ClusteredIndex):定义:聚簇索引是按照索引的顺序直接排列数据表的行的一种索引结构。实际上,聚簇索引决定了数据表的物理排序方式。主键:通常,聚簇索......
  • java中%的含义,千万别弄反了!!!
    i%j代表的是i除以j的余数,比如5%2=1,千万别弄反了!!!因为敲代码时候弄反,导致结果出错/*题目:找出100以内所有素数/质数,10000以内的呢*/publicclassPrimeNumberTest{publicstaticvoidmain(String[]args){for(inti=1;i<=100;i++){booleanisFlag=tr......
  • Java_2 判断语句
    1if语句1.1基本if-else语句当条件成立时,执行某些语句;否则执行另一些语句。importjava.util.Scanner;publicclassMain{publicstaticvoidmain(String[]args){Scannersc=newScanner(System.in);inta=sc.nextInt();if......
  • Java_1 变量、运算符、表达式、输入与输出
    1编写一个简单的Java程序–手速练习publicclassMain{publicstaticvoidmain(String[]args){System.out.println("HelloWorld");}}2语法基础2.1变量变量必须先定义,才可以使用。不能重名。变量定义的方式:publicclassMain{publicstat......