以前使用 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);} }