在开发一些远程过程调用(RPC)的程序时,一般都会涉及到对象的序列化和反序列化的问题(因为TCP或UDP这些低层协议只能传输字节流,所以应用层需要将Java POJO对象序列化为字节流才能传输)。
对象的序列化方式有以下几种方式:
- JSON:将Java POJO对象转换成JSON结构化的字符串。一般用于Web应用和移动开发,可读性较强,性能较差。
- XML:与JSON一样,也是序列化为字符串,只是格式不同,可读性强,一般用于异构系统。
- JDK内置序列化:将Java POJO对象转换成二进制字节数组,可移植性强,性能较差,可读性差。
- Protobuf:类似JDK内置序列化,Google开源的高性能、易扩展框架,一般用于高性能通信。
一般常用的序列化方式就是JSON(性能要求不太高的Web开发等)和protobuf(高性能应用,比如和Netty一起实现高性能通信)。
JSON
JSON序列化框架
使用的比较多的两个开源的处理JSON的类库:
- FastJson:这是阿里开源的一个高性能的JSON库,采用独创的算法,将JSON转为Java POJO对象的速度非常快,但将复杂的POJO转换成JSON时可能会出错。
- Gson:这是Google开源的一个非常完善的JSON解析库,可以完成复杂类型的POJO和JSON之间的相互转换。
结合两者的优势,一般策略是:将POJO转为JSON时使用Gson(序列化),将JSON转成POJO时使用FastJson(反序列化)。
下面是一个FastJson和Gson结合使用的JSON工具类。
public class JsonUtil {
// 构造一个Gson的构建器
private static GsonBuilder builder = new GsonBuilder();
static {
// 禁用Html的序列化
builder.disableHtmlEscaping();
}
/**
* POJO的序列化
* @return 使用Google的Gson框架
*/
public static String convertJson(){
// 使用构建者模式创建一个Gson对象
Gson gson = builder.create();
MsgProto.Person person = ProtobufDemo.buildPerson();
// 使用Gson将POJO转换成JSON字符串
return gson.toJson(person);
}
/**
* 将json反序列化为POJO
* 使用阿里的FastJson
* @param json 要反序列化的json
* @param clazz 要反序列化的原型
* @param <T> 泛型
* @return 反序列化后的POJO
*/
public static <T>T parseFromJson(String json, Class<T> clazz){
// 使用FastJson将JSON转换成对应得POJO
return JSONObject.parseObject(json, clazz);
}
}
JSON序列化和反序列化实践
首先定义一个POJO类Person,里面调用JsonUtil工具类的方法来实现序列化和反序列化。
public class Person {
private int id;
private String name;
private String phone;
private String address;
public Person(int id, String name, String phone, String address) {
this.id = id;
this.name = name;
this.phone = phone;
this.address = address;
}
/**
* 序列化成JSON
* @return JSON字符串
*/
public String convertToJson(){
return JsonUtil.convertJson(this);
}
/**
* 反序列化为对象,这是个静态方法
* @param json JSON字符串
* @return 对象
*/
public static Person parseFromJson(String json){
return JsonUtil.parseFromJson(json, Person.class);
}
@Override
public String toString() {
return super.toString() + "name = " + name + " phone = " + phone + " address = " + address;
}
}
再写一个测试方法(使用了Junit测试框架),测试pojo的序列化和反序列化。
@Test
public void testJson(){
Person person = new Person(1, "monkJay", "13330114338", "江西九江");
// 将对象序列化为JSON字符串
String json = person.convertToJson();
LogUtil.info("序列化为JSON后的数据: [{}]",json);
// 将JSON字符串反序列化为对象
Person person1 = Person.parseFromJson