通用的ProtostuffSerializer for Java

以前使用 protobuf或protostuff的时候觉得很麻烦,每个类都要单独定制,于是封装了一个类。

同事测试过,性能和压缩率都很好,尤其是相比json的序列化。

需注意:只支持Pojo类(即需要有get/set方法)、对一个新的class第一次调用初始化会有一两百毫秒的register时间,之后就很快了。

import io.protostuff.LinkedBuffer;
import io.protostuff.ProtostuffIOUtil;
import io.protostuff.Schema;
import io.protostuff.runtime.RuntimeSchema; import java.io.Serializable;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; /**
* Protostuff serializer tool, for POJO serialization.
* Protostuff is much more efficient than json, even faster than Protobuf and Avro, but the serialized string is human-unreadable.
* Not support Array or Generic-type, please wrap these special objects via a POJO with empty constructors.
*
* @author lhfcws
* @since 2016-03-16
*/
public class ProtostuffSerializer implements Serializable { static Map<Class, Schema> schemaCache = new ConcurrentHashMap<>(); /**
* common protostuff serialize, object need a empty constructor
* Be careful to convert result byte[] to String, use new String(bytes, StandardCharsets.UTF_16LE).
*
* @param obj
* @param <T>
* @return
*/
public static <T> byte[] serializeObject(T obj) {
Class<T> klass = (Class<T>) obj.getClass();
LinkedBuffer buffer = LinkedBuffer.allocate(4096);
try {
if (schemaCache.containsKey(klass)) {
return ProtostuffIOUtil.toByteArray(obj, schemaCache.get(klass), buffer);
} else {
schemaCache.put(klass, RuntimeSchema.getSchema(klass));
return ProtostuffIOUtil.toByteArray(obj, schemaCache.get(klass), buffer);
}
} finally {
buffer.clear();
}
} /**
* common protostuff unserialize
*
* @param bs
* @param klass
* @param <T>
* @return
*/
public static <T> T deserialize(byte[] bs, Class<T> klass) {
if (schemaCache.containsKey(klass)) {
Schema<T> schema = schemaCache.get(klass);
T msg = schema.newMessage();
ProtostuffIOUtil.mergeFrom(bs, msg, schema);
return msg;
} else {
Schema<T> schema = RuntimeSchema.getSchema(klass);
T msg = schema.newMessage();
schemaCache.put(klass, schema);
ProtostuffIOUtil.mergeFrom(bs, msg, schema);
return msg;
}
}
}

使用demo:

// 如果是Pojo类直接调用就行了,非Pojo类参考如下:(假设已有一个StrParams model类)

    public static class StrParamsPojo {
private StrParams p; public StrParamsPojo() {
} public StrParamsPojo(StrParams p) {
this.p = p;
} public StrParams getP() {
return p;
} public void setP(StrParams p) {
this.p = p;
}
} public void serialize() throws IOException {
StrParams p = new StrParams();
StrParamsPojo pojo = new StrParamsPojo(p);
byte[] bs = ProtostuffSerializer.serializeObject(pojo);
} public void deserialize(byte[] bs) throws IOException {
StrParamsPojo pojo = ProtostuffSerializer.deserialize(bs, StrParamsPojo.class);
StrParams p = pojo.getP();
}

附送一个FastJsonSerializer:

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature; import java.lang.reflect.Type; /**
* FastJson is faster than Gson.
* But DO remember your objects has get/set for the fields you want to serialze.
* @author lhfcws
*/
public class FastJsonSerializer { /**
* 把给定的对象序列化成json字符串
* @param obj 给定的对象
* @return 对象序列化后的json字符串
*/
public static <T> String serialize(T obj) {
return JSON.toJSONString(obj,
SerializerFeature.IgnoreNonFieldGetter,
SerializerFeature.SkipTransientField,
SerializerFeature.DisableCircularReferenceDetect,
SerializerFeature.BrowserCompatible
);
} public static <T> String serializePretty(T obj) {
return JSON.toJSONString(obj,
SerializerFeature.IgnoreNonFieldGetter,
SerializerFeature.SkipTransientField,
SerializerFeature.DisableCircularReferenceDetect,
SerializerFeature.BrowserCompatible,
SerializerFeature.PrettyFormat
);
} /**
* 根据类名把json字符串反序列化成实体类对象
* @param json 待反序列化的json字符串
* @param klass 反序列化的实体类
* @return 反序列化后的对象
*/
public static <T> T deserialize(String json, Class<T> klass) {
return JSON.parseObject(json, klass);
} /**
* 把Json字符串反序列化成实现了Type接口的实体类对象
* @param json 待反序列化的json字符串
* @param type 泛型类型
* @return 反序列化后的对象
*/
public static <T> T deserialize(String json, Type type) {
return JSON.parseObject(json, type);
}
}
上一篇:优先使用TimeUnit类中的sleep()


下一篇:ASP.NET MVC中使用Unity进行依赖注入的三种方式