Byter

字节对象转换框架,一个基于字节的 Gson/FastJson

众所周知,Json数据的序列化内容就是字符串,如果说Gson/FastJson是基于字符串的Json转化框架,那么Byter就是基于字节流的Json转化框架。

设计Byter之处,就是为了快速且优雅地解析一些底层协议,如蓝牙、TCP/IP、MQTT等,均需要通过解析字节流来转换数据。在正常的开发流程中,往往都是采用写死下标的方法来处理字节数据,这种处理一般情况下还好,如若一旦涉及到协议增删改,那就非常头疼了。要是再多改上几次,最好再改改数据结构,恐怕就会怀疑自己是否适合从事开发行业了。

为了让字节数据解析像Gson/FastJson那样简单粗暴,因此我设计了Byter。而Byter的使用相当简便,只需要掌握三步骤即可:

第一步:按照协议定义你的对象属性字段;

需要注意的是,字段的数据类型必须与你的协议一一对应。如:协议定义了一个 2字节大小的head,那么在对象中定义的head也应该是一个short而不能定义为int。因为java标准中int占4个字节,长度不相同当然不能混定义,不太清楚各个基础数据类型占用的字节大小的话可以自行搜索一下。

class InfoData{

short head;

byte cmd;

short version;

short extra;

byte sum;

}

补充:Byter支持所有的基础数据类型与String,不推荐也不支持使用基础数据的包装类。因为包装类的拆箱装箱效率较低,且包装类的执行时间和占用内存远大于基础类型,所以从性能的角度上考虑直接禁用了包装类。

第二步:标注字段顺序

按照协议的字段顺序,在你的属性字段上使用@Order的注解描述你的协议顺序。

需要注意的是,字段的标注顺序并不一定要求1、2、3、4、5这样依次递增,只要满足大小规律即可,如1,10,20,21,22,25,100。这样可以预留一些余地让子类来定义。

class InfoData{

@Order(order = 1)

short head;

@Order(order = 2)

byte cmd;

@Order(order = 10)

short version;

@Order(order = 11)

short extra;

@Order(order = 20)

byte sum;

}

第三步:

使用Byter的 toBytes 或者 fromBytes ,体验数据与对象的一键转化。

InfoData infoData = Byter.fromBytes(InfoData.class,bytes);

有些朋友可能会问了:完了,就这??当然,基础的使用方式仅此而已,但真实的情况肯定不会这么简单。在我们的实际应用中,一个对象里可能还会嵌套N级对象;并且有些数据还是数组,而对于字节协议来说数组的学问就多了,有些协议的数组定长,有些协议的数组需要根据某个字段的值来决定,还有一些协议既不定长也不需要定义,这么多需求都能满足?

对于以上情况,都是框架者需要考虑的问题,Byter不一定能保证全部满足需求,不过对于正常流程的需求Byter全部都考虑到了。对于一些不太常见但是确实存在的协议,也可以与我私聊,Byter会通过迭代尽力满足大家。同时Byter的源码也是非常精简的,一共2个类+2个注解,可以随时拷贝走自己改改源码。

首先对于第一个问题:对象里面可能会嵌套N层对象——这个完全不需要担心,Byter使用递归的方式处理了任意层级的对象数据,并且支持多层继承的关系,你只需要担心自己的对象是否按照协议定义。

class Parent {

@Order(order = 1)

short head;

@Order(order = 2)

byte cmd;

@Order(order = 100)

byte sum;

}

class Child extends Parent{

@Order(order = 10)

Data1 data1;

@Order(order = 11)

Data2 data2;

}

class Data1{

@Order(order = 1)

int x;

@Order(order = 2)

long y;

@Order(order = 3)

short z;

}

class Data2{

@Order(order = 1)

double a;

@Order(order = 2)

float b;

}

其次第二个问题,对于数组类型的数据来说Byter也有一套解决方案:通过在数组字段上标注@Length的方式来描述数组的长度。

@Length有两个方法,分别是 length 和 lengthByField。如果你的数组长度固定,那么使用 length = n 的方式来定义,如果是依赖某个字段的值的话,那就使用lengthByField = “fieldName”来定义。如果数组既不定长,也不依赖某个字段,那么就不需要用这个注解。Byter会计算后面的字段长度,再根据总长,从而推导出当前的数组长度。当然,这样就必须要求你的协议中不能同时存在两个以上的数组,否则无法推导。

还有两点需要说明:@1 数组既可以是基础数据类型,也可以是对象。 @2 String 等同于 byte[] 类型。

定长:

class ExampleArray{

@Order(order = 1)

short head;

@Order(order = 2)

byte cmd;

//数组字段

@Length(length = 5)

@Order(order = 10)

KeyValue[] keyValues;

@Order(order = 100)

byte sum;

}

class KeyValue {

@Order(order = 1)

byte key;

@Order(order = 2)

short value;

}

依赖某个字段:

class ExampleArray{

@Order(order = 1)

short head;

@Order(order = 2)

byte cmd;

//假设下面的keyValues长度由本字段决定

@Order(order = 10)

byte count;

//数组字段

@Length(lengthByField = "count")

@Order(order = 11)

KeyValue[] keyValues;

@Order(order = 100)

byte sum;

}

class KeyValue {

@Order(order = 1)

byte key;

@Order(order = 2)

short value;

}

自动推导:(要求协议中不能存在两个及两个以上的数组,否则推导失败,同时协议中如果有补0填充的处理那么也将失去意义)

class ExampleArray{

@Order(order = 1)

short head;

@Order(order = 2)

byte cmd;

@Order(order = 11)

byte[] bytes;

@Order(order = 100)

byte sum;

}

如果在转换的过程中,需要用到一些额外加工途径才能生成最终的数据,或者在转换的过程中需要判断一些值的条件以决定后续;Byter也提供了相应的接口: ToBytesConverter 与 FromBytesConverter。

你可以通过重写 interceptToBytes 或者 interceptFromBytes 并通过返回true的形式自定义某些字段的转换结果。如果返回false则表示不对此字段进行拦截,一般情况下你只需要拦截需要特殊处理的字段即可。

如果在解析的过程中发现某些数据可能存在问题,你可以通过 throw new Execption 的方式及时抛出异常,以中止本次数据转换。

同时Byter还提供了 finishToBytes 和 finishFromBytes 方法,可以在最终转换数据前,做最终处理(加密解密等检验计算等)。

有一点需要特别指明:以上所有方法中都含有ByteBuffer参数,对此类不太熟悉的朋友一定要看ByteBuffer的使用事项。通过flip读取数据之后一定要再flip回来,并且read和get时也要保证没有多次调用。相信用过ByteBuffer的同学都明白我的意思,谨记谨记!

最后,都看到这儿,给个start再走吧。别别别走,我是开玩笑的,我是一个代码完美主义者,喜欢用优雅地方式解决一些常见的问题,如果你跟我志同道合,可以私聊或者邮件@我,欢迎一起搞基哦!

java byter是字节吗_GitHub - XXQAQ/Byter: 字节对象转换框架,一个基于字节的 Gson/FastJson...相关推荐

  1. 开源我的基于字节的数据补丁算法库HDiffPatch

    开源我的基于字节的数据补丁算法库HDiffPatch 作者: HouSisong@GMail.com   2013.05.31 tag: HDiffPatch,diff,patch,补丁 HDiffP ...

  2. 【java笔记】IO流(1):IO流概述,字节输出/输入流读写文件

    IO概述: I: input( 读取 ) 把硬盘中的数据,读取到内存中使用 O: output(写入)  把内存中的数据,写入到硬盘中保存 流:数据(字符,字节)1个字符=2个字节 ,1个字节=8个二 ...

  3. java一个byte字节可以存2个16进制字符

    一个字节是8位(bit),xxxxxxxx ,范围从00000000 - 11111111,表示0到255. 一个16进制字符(用二进制表示是xxxx)最多只表示到10进制的15(即16进制的F) 要 ...

  4. java map 结构体_业务代码的救星——Java 对象转换框架 MapStruct 妙用

    简介 在业务项目的开发中,我们经常需要将 Java 对象进行转换,比如从将外部微服务得到的对象转换为本域的业务对象 domain object,将 domain object 转为数据持久层的 dat ...

  5. Java-Java I/O流解读之基于字节的I / O和字节流

    概述 File and Directory Class javaioFile Pre-JDK 7 Verifying Properties of a FileDirectory List Direct ...

  6. JVM运行时结构、Java内存管理、JVM实例、HotSpot VM对象的创建、内存布局和访问定位

    1.JVM运行时结构 Java 运行时数据区域有程序计数器.Java虚拟机栈.本地方法栈.Java堆和方法区.其中前三个线程私有,随线程生而生,线程灭而灭:后面两个是线程间共享. 1.1 程序计数器 ...

  7. 定义一个dto对象_业务代码的救星——Java 对象转换框架 MapStruct 妙用

    在业务项目的开发中,我们经常需要将 Java 对象进行转换,比如从将外部微服务得到的对象转换为本域的业务对象 domainobject,将 domainobject 转为数据持久层的 dataobje ...

  8. char怎么比较_为什么阿里巴巴Java开发手册中强制要求整型包装类对象值用 equals 方法比较?...

    在阅读<阿里巴巴Java开发手册>时,发现有一条关于整型包装类对象之间值比较的规约,具体内容如下: 这条建议非常值得大家关注, 而且该问题在 Java 面试中十分常见. 还需要思考以下几个 ...

  9. java socket发送定长报文_一个基于TCP协议的Socket通信实例

    原标题:一个基于TCP协议的Socket通信实例 1. 前言 一般接口对接多以http/https或webservice的方式,socket方式的对接比较少并且会有一些难度.正好前段时间完成了一个so ...

最新文章

  1. R语言tidyr包pivot_longer函数、pivot_wider函数数据表变换实战(长表到宽表、宽表到长表)
  2. 配置系统在开机时启动虚拟机
  3. 前端JS: 通过代码-看函数作用域this对象
  4. 电商系统设计之商品(上)
  5. 图像降噪算法——Variance Stabilizing Transform / Generalization Anscombe Transform算法
  6. SAP Spartacus Page Layout - 页面布局设计
  7. CSDN博客图片水印|自定义水印|去除水印
  8. MVC的初步认识理论
  9. 3d激光雷达开发(生成RangeImage)
  10. 为什么我花了三个半月准备的面试还是砸了?附 iOS 开发者求职攻略
  11. linux oracle pam,Linux下安装Oracle11g软、硬件环境检测和修改
  12. Win10验证USB Audio MIC(三)
  13. Visio2019自动闪退问题
  14. java学习(eclipse环境的使用)
  15. Python中字母大小写转换
  16. Faster-RCNN的关键点总结
  17. EasyExcel学习笔记
  18. Designing Data-Intensive Applications翻译
  19. 三星证实遭黑客入侵:Galaxy手机源代码泄露
  20. 终于搞懂Dijkstra算法了

热门文章

  1. corosync+pacemaker+crmsh的高可用web集群的实现
  2. Aruba发布全新集成资产追踪解决方案及核心交换机
  3. iphone6 iphone6 plus 放大显示模式高分辨率模式问题
  4. uva 707(记忆化搜索)
  5. 【原译】在amazon kindle上安装Metasploit
  6. javax.validation.ParameterNameProvider
  7. apache和tomcat区别
  8. python3 bytes与hex字符串互转
  9. python 类实例化理解
  10. PHP数组键值双引号单引号区别