在Java中, 序列化是一种把java对象状态转化成字节码流形式的机制, 这种机制被应用在RPC, Hibernate, RMI, JPA, EJB 和 JMS等场景中; 序列化的逆向操作是反序列化, 顾名思义, 就是把java对象的字节码流还原到jvm中的运行时对象;
常见的序列化方式
- Standard Java Serialization API(java平台标志API)
- Json(JavaScript Object Notation)对象与文本互转的一种序列化方式。
- Protocol buffers对象二进制存储格式。
Standard Java Serialization API
Java 平台标准序列化与反序列化, 需要class实现Serializable接口, 再由相关的对象流读写工具[ObjectOutputStream, ObjectInputStream]来执行默认操作实现;
- java中, 如果想要对一个对象进行标准的序列化与反序列化操作, 那这个对象所属 class 必须实现 Serializable 接口;
- Serializable 是jdk中一个标识性接口, 既没有成员变量也没有方法, 类似的接口还有 Cloneable, Remote;
- 父类实现 Serializable 接口, 所有子类都继承实现此接口, 也就同样可以进行序列化与反序列化操作;
- 序列化和反序列化一个 class 的对象时, 需要有一个 serialVersionUID, 如果我们编码时不在 class 定义里面指定, 序列化时会默认生成,
这个版本号可以用来标识同一个 class 不同版本, 如果反序列化与序列化时的 serialVersionUID 不一致会报 InvalidClassException 异常; - 序列化一个对象时, 如果它包含了没有实现 Serializable 接口的引用类型属性, 那就会在序列化时抛出 NotSerializableException 异常;
- 序列化的信息格式大致为: class 描述开头标志位|class name| class serialVersionUID|序列化标志位|包含属性成员个数|[{属性类型|属性值}]|结束标识符
- 如果 class 里面的属性被声明为 transient , 那对应的属性就不会被序列化;
- 与 Serializable 关联的还有个 Externalizable 接口, 它里面有两个方法, 可以实现序列化与反序列化过程中的自定义控制, 因为 Serializable 本身默认的
序列化逻辑太重了, 它可能会生成过多的我们不需要内容, 网络传输传递的多了也会更耗时, 所以我们可以自定义序列化哪些需要的属性;
具体实现代码:
- Master: 实现 Serializable 接口的class, 构造出来的对象可以被进行默认的序列化与反序列化操作;
- Book: 实现 Externalizable 接口的class, 构造出来的对象可以按照自定义的方式进行序列化与反序列化操作;
- Serialize: 序列化操作示例;
- Deserialize: 反序列化的操作示例;
Json(JavaScript Object Notation)
Json是一种轻量级的数据交换格式。 易于人阅读和编写, 也易于机器解析和生成。Json字符串的构建主要基于两种数据结构,对象和数组; 不同的开发语言都实现了各自不同对象Json序列化功能, 在Java中比较好用的 fastjson, gson, jackson等;
Json规范的特性:
- 只有两种结构:对象内的键值对集合结构和数组,对象用{}表示、内部是”key”:”value”,数组用[]表示,不同值用逗号分开
- 基本数值有7个: false / null / true / object / array / number / string
- 基于纯文本,所以对于人类阅读是很友好的。
使用fastjson实现Json操作示例:
- 被序列化的对象-class无需实现Serializable接口;
- 依靠class中的构造方法或者get/set方法实现序列化与反序列化操作;
- 在反序列化过程中, 如果没有无参构造方法, 会调用有参构造方法为对象中的属性赋值;
fastjson目前支持的特性:
- QuoteFieldNames: 属性用引号括起来
- UseSingleQuotes: 使用单引号
- WriteMapNullValue: 输出Map的null值
- WriteEnumUsingToString: 枚举属性输出toString的结果
- WriteEnumUsingName: 枚举数据输出name
- UseISO8601DateFormat: 使用日期格式
- WriteNullListAsEmpty: List为空则输出[]
- WriteNullStringAsEmpty: String为空则输出””
- WriteNullNumberAsZero: Number类型为空则输出0
- WriteNullBooleanAsFalse: Boolean类型为空则输出false
- SkipTransientField: 忽略transient字段
- SortField: 字段排序
- WriteTabAsSpecial:
- PrettyFormat:
- WriteClassName:
- DisableCircularReferenceDetect:
- WriteSlashAsSpecial:
- BrowserCompatible:
- WriteDateUseDateFormat:
- NotWriteRootClassName:
- DisableCheckSpecialChar:
- BeanToArray:
- WriteNonStringKeyAsString:
- NotWriteDefaultValue:
- BrowserSecure:
- IgnoreNonFieldGetter:
- WriteNonStringValueAsString:
- IgnoreErrorGetter:
- WriteBigDecimalAsPlain:
- MapSortField:
具体实现代码:
- Serialize: 常见序列化的操作示例;
- CustomSerialize : 自定义序列化操作示例;
Protocol buffers
Protocol buffers是一种灵活高效的数据结构化存储格式,用于结构型数据序列化,适合数据存储或RPC数据交互。具有语言无关、平台无关、可扩展的序列化结构数据格式。