Java MessagePack序列化工具(适配Unity)

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

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值