Java MessagePack序列化工具(适配Unity)
- 前言
- 项目
- 代码编写
- 结
前言
前后端统一用MessagePack,结果序列化的结果不一样,发现C#侧需要给每个类增加描述字段数量的Head,而Java却不用,所以在Java侧封装一下序列化和反序列化方法,这样两边解析的内容就完全一致了。
项目
代码编写
感觉还有很大的压缩空间
import org.msgpack.core.MessageBufferPacker;
import org.msgpack.core.MessagePack;
import org.msgpack.core.MessageUnpacker;
import java.io.IOException;
import java.lang.reflect.*;
import java.util.*;
public class MessagePackSerializer {
public static byte[] serialize(Object obj) throws IOException, IllegalAccessException {
try (MessageBufferPacker packer = MessagePack.newDefaultBufferPacker()) {
serializeObject(obj, packer);
return packer.toByteArray();
}
}
public static <T> T deserialize(byte[] data, Class<T> clazz) throws IOException, IllegalAccessException,
InstantiationException, InvocationTargetException, NoSuchMethodException, ClassNotFoundException {
try (MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(data)) {
return clazz.cast(deserializeObject(clazz, unpacker));
}
}
private static void serializeObject(Object obj, MessageBufferPacker packer)
throws IOException, IllegalAccessException {
if (obj == null) {
packer.packNil();
return;
}
Class<?> clazz = obj.getClass();
List<Field> allFields = new ArrayList<>();
while (clazz != null) {
Field[] fields = clazz.getDeclaredFields();
allFields.addAll(Arrays.asList(fields));
clazz = clazz.getSuperclass(); // 处理父类字段
}
packer.packArrayHeader(allFields.size());
for (Field field : allFields) {
field.setAccessible(true);
Object value = field.get(obj);
serializeValue(value, packer);
}
}
private static Object deserializeObject(Class<?> clazz, MessageUnpacker unpacker) throws IOException,
IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchMethodException,
ClassNotFoundException {
if (unpacker.tryUnpackNil()) {
return null;
}
Object obj = clazz.getDeclaredConstructor().newInstance();
int fieldCount = unpacker.unpackArrayHeader();
List<Field> allFields = new ArrayList<>();
while (clazz != null) {
Field[] fields = clazz.getDeclaredFields();
allFields.addAll(Arrays.asList(fields));
clazz = clazz.getSuperclass();
}
for (int i = 0; i < fieldCount; i++) {
Field field = allFields.get(i);
field.setAccessible(true);
Object value = deserializeValue(field.getType(), unpacker, getFieldGenericType(field));
field.set(obj, value);
}
return obj;
}
private static void serializeValue(Object value, MessageBufferPacker packer)
throws IOException, IllegalAccessException {
if (value == null) {
packer.packNil();
} else if (value instanceof String) {
packer.packString((String) value);
} else if (value instanceof Integer) {
packer.packInt((Integer) value);
} else if (value instanceof Long) {
packer.packLong((Long) value);
} else if (value instanceof Float) {
packer.packFloat((Float) value);
} else if (value instanceof Double) {
packer.packDouble((Double) value);
} else if (value instanceof Boolean) {
packer.packBoolean((Boolean) value);
} else if (value instanceof List) {
List<?> list = (List<?>) value;
packer.packArrayHeader(list.size());
for (Object item : list) {
serializeValue(item, packer);
}
} else if (value instanceof Map) {
Map<?, ?> map = (Map<?, ?>) value;
packer.packMapHeader(map.size());
for (Map.Entry<?, ?> entry : map.entrySet()) {
serializeValue(entry.getKey(), packer);
serializeValue(entry.getValue(), packer);
}
} else {
serializeObject(value, packer);
}
}
private static Object deserializeValue(Class<?> type, MessageUnpacker unpacker, Type genericType)
throws IOException, IllegalAccessException, InstantiationException, InvocationTargetException,
NoSuchMethodException, ClassNotFoundException {
if (unpacker.tryUnpackNil()) {
return null;
} else if (type == String.class) {
return unpacker.unpackString();
} else if (type == Integer.class || type == int.class) {
return unpacker.unpackInt();
} else if (type == Long.class || type == long.class) {
return unpacker.unpackLong();
} else if (type == Float.class || type == float.class) {
return unpacker.unpackFloat();
} else if (type == Double.class || type == double.class) {
return unpacker.unpackDouble();
} else if (type == Boolean.class || type == boolean.class) {
return unpacker.unpackBoolean();
} else if (List.class.isAssignableFrom(type)) {
int size = unpacker.unpackArrayHeader();
List<Object> list = new ArrayList<Object>(size);
for (int i = 0; i < size; i++) {
Type listItemType = (genericType instanceof ParameterizedType)
? ((ParameterizedType) genericType).getActualTypeArguments()[0]
: Object.class;
list.add(deserializeValue((Class<?>) listItemType, unpacker, listItemType));
}
return list;
} else if (Map.class.isAssignableFrom(type)) {
int size = unpacker.unpackMapHeader();
Map<Object, Object> map = new HashMap<Object, Object>(size);
Type keyType = (genericType instanceof ParameterizedType)
? ((ParameterizedType) genericType).getActualTypeArguments()[0]
: String.class;
Type valueType = (genericType instanceof ParameterizedType)
? ((ParameterizedType) genericType).getActualTypeArguments()[1]
: Object.class;
for (int i = 0; i < size; i++) {
Object key = deserializeValue((Class<?>) keyType, unpacker, keyType);
Object value = deserializeValue((Class<?>) valueType, unpacker, valueType);
map.put(key, value);
}
return map;
} else {
return deserializeObject(type, unpacker);
}
}
private static Type getFieldGenericType(Field field) {
return field.getGenericType();
}
}
结
如果有优化会放到下面这个地址
JavaMsgPack-Utility