MessagePack封装,支持注解

import com.tianxiawuxue.commons.util.ZipUtil;
import org.msgpack.core.MessageBufferPacker;
import org.msgpack.core.MessagePack;
import org.msgpack.core.MessageUnpacker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;

import java.io.IOException;
import java.lang.reflect.*;
import java.util.*;


/**
 * description: 使用开源包MessagePack,实现对象的序列化和反序列化.
 * 如果序列化的结果很大, 则执行zlib返回
 *
 * @author 天下武学
 * date 2020-07-02 19:18
 **/
public class MessagePackSerialize {
    private static final int MAX_LENGTH = 1024;
    private static final Logger logger = LoggerFactory.getLogger(MessagePackSerialize.class);
    private static final WeakHashMap<Class, List<FieldAnnotation>> FIELD_WEAK_HASH_MAP = new WeakHashMap<>();


    public static <T> byte[] toBytes(T obj) {
        try (MessageBufferPacker packer = MessagePack.newDefaultBufferPacker()) {
            packObject(obj, packer);
            return zip(packer.toByteArray());
        } catch (IOException | IllegalAccessException e) {
            logger.error("MessagePackSerialize.toBytes.Exception, " + obj, e);
        }
        return null;
    }

    @SuppressWarnings("unchecked")
    private static <T> void packObject(T obj, MessageBufferPacker packer) throws IOException, IllegalAccessException {
        if (obj == null) {
            packer.packNil();
            return;
        }
        if (obj instanceof Collection) {
            packCollection((Collection) obj, packer);
        } else if (obj instanceof Map) {
            packMap((Map) obj, packer);
        } else if (obj.getClass().isArray()) {
            packArray(obj, packer);
        } else if (isBoxingClass(obj)) {
            packBoxingData(obj, packer);
        } else {
            byte[] bytes = classToBytes(obj);
            if (bytes == null) {
                packer.packNil();
            } else {
                if (packer.toByteArray().length > 0) {
                    packer.packInt(bytes.length);
                }
                packer.writePayload(bytes);
            }
        }
    }

    private static <T> byte[] classToBytes(T obj) throws IOException, IllegalAccessException {
        try (MessageBufferPacker packer2 = MessagePack.newDefaultBufferPacker()) {
            List<FieldAnnotation> fieldAnnotationList = getFiledAnnotation(obj.getClass());
            for (FieldAnnotation fieldAnnotation : fieldAnnotationList) {
                Class typeClass = fieldAnnotation.field.getType();
                Object fieldValue = fieldAnnotation.field.get(obj);
                if (fieldValue == null) {
                    packer2.packNil();
                    continue;
                }
                switch (typeClass.getName()) {
                    case "int":
                        packer2.packInt(fieldAnnotation.field.getInt(obj));
                        break;
                    case "long":
                        packer2.packLong(fieldAnnotation.field.getLong(obj));
                        break;
                    case "short":
                        packer2.packShort(fieldAnnotation.field.getShort(obj));
                        break;
                    case "byte":
                        packer2.packByte(fieldAnnotation.field.getByte(obj));
                        break;
                    case "double":
                        packer2.packDouble(fieldAnnotation.field.getDouble(obj));
                        break;
                    case "float":
                        packer2.packFloat(fieldAnnotation.field.getFloat(obj));
                        break;
                    case "char":
                        packer2.packInt(fieldAnnotation.field.getChar(obj));
                        break;
                    case "bool":
                        packer2.packBoolean(fieldAnnotation.field.getBoolean(obj));
                        break;
                    default:
                        packObject(fieldAnnotation.field.get(obj), packer2);
                        break;
                }
            }
            return packer2.toByteArray();
        }
    }

    private static <T> void packCollection(Collection<T> list, MessageBufferPacker packer) throws IOException, IllegalAccessException {
        if (list == null) {
            packer.packNil();
            return;
        }
        packer.packInt(list.size());
        for (T t : list) {
            packObject(t, packer);
        }
    }

    private static void packArray(Object array, MessageBufferPacker packer) throws IOException, IllegalAccessException {
        if (array == null) {
            packer.packNil();
            return;
        }
        if (!array.getClass().isArray()) {
            throw new RuntimeException("packArray method error. array: " + array);
        }
        if (array.getClass().getName().equals(DataEnum.ARRAY_INT.clazz)) {
            int[] kk = (int[]) array;
            packer.packInt(kk.length);
            for (int k : kk) {
                packer.packInt(k);
            }
        } else if (array.getClass().getName().equals(DataEnum.ARRAY_INT_BOX.clazz)) {
            Integer[] kk = (Integer[]) array;
            packer.packInt(kk.length);
            for (int k : kk) {
                packer.packInt(k);
            }
        } else if (array.getClass().getName().equals(DataEnum.ARRAY_LONG.clazz)) {
            long[] kk = (long[]) array;
            packer.packInt(kk.length);
            for (long k : kk) {
                packer.packLong(k);
            }
        } else if (array.getClass().getName().equals(DataEnum.ARRAY_LONG_BOX.clazz)) {
            Long[] kk = (Long[]) array;
            packer.packInt(kk.length);
            for (long k : kk) {
                packer.packLong(k);
            }
        } else if (array.getClass().getName().equals(DataEnum.ARRAY_BYTE.clazz)) {
            byte[] kk = (byte[]) array;
            packer.packInt(kk.length);
            packer.writePayload(kk);
        } else if (array.getClass().getName().equals(DataEnum.ARRAY_BYTE_BOX.clazz)) {
            Byte[] kk = (Byte[]) array;
            packer.packInt(kk.length);
            for (Byte k : kk) {
                packer.packByte(k);
            }
        } else {
            throw new RuntimeException("not support array of " + array.getClass());
        }
    }

    private static <K, V> void packMap(Map<K, V> map, MessageBufferPacker packer) throws IOException, IllegalAccessException {
        if (map == null) {
            packer.packNil();
            return;
        }
        packer.packInt(map.size());
        for (Map.Entry<K, V> entry : map.entrySet()) {
            packObject(entry.getKey(), packer);
            packObject(entry.getValue(), packer);
        }
    }

    private static <T> void packBoxingData(T t, MessageBufferPacker packer) throws IOException {
        if (t == null) {
            packer.packNil();
            return;
        }
        if (t.getClass().equals(Boolean.class)) {
            packer.packBoolean((Boolean) t);
        } else if (t.getClass().equals(Byte.class)) {
            packer.packByte((Byte) t);
        } else if (t.getClass().equals(Short.class)) {
            packer.packShort((Short) t);
        } else if (t.getClass().equals(Character.class)) {
            packer.packInt((Character) t);
        } else if (t.getClass().equals(Integer.class)) {
            packer.packInt((Integer) t);
        } else if (t.getClass().equals(Long.class)) {
            packer.packLong((Long) t);
        } else if (t.getClass().equals(Float.class)) {
            packer.packFloat((Float) t);
        } else if (t.getClass().equals(Double.class)) {
            packer.packDouble((Double) t);
        } else if (t.getClass().equals(String.class)) {
            packer.packString((String) t);
        } else {
            throw new RuntimeException("MessagePackSerialize.pack.not support T.class = " + t.getClass());
        }
    }

    /**
     * T 是基础类型的封装类
     *
     * @param t   t
     * @param <T> T
     * @return true:是基础类型,可直接pack
     */
    private static <T> boolean isBoxingClass(T t) {
        if (t == null) {
            return false;
        }
        Class clazz = (t instanceof Class) ? (Class) t : t.getClass();

        return Boolean.class.equals(clazz) || Byte.class.equals(clazz) || Short.class.equals(clazz) || Character.class.equals(clazz)
                || Integer.class.equals(clazz) || Long.class.equals(clazz) || Float.class.equals(clazz) || Double.class.equals(clazz) ||
                String.class.equals(clazz) ;
    }


    public static <T> T parseObject(byte[] bytes, Class<T> clazz) {
        return parseObject(bytes, clazz, null, true);
    }

    public static <T> T parseObject(byte[] bytes, Class<T> clazz, Type[] type) {
        return parseObject(bytes, clazz, type, true);
    }

    private static <T> T parseSubObject(byte[] bytes, Class<T> clazz) {
        return parseObject(bytes, clazz, null, false);
    }

    private static <T> T parseObject(byte[] bytes, Class<T> clazz, Type[] type, boolean isZip) {
        if (bytes == null) {
            return null;
        }
        try (MessageUnpacker unPacker = MessagePack.newDefaultUnpacker(isZip ? unzip(bytes) : bytes)) {
            return parseObject(unPacker, clazz, type);
        } catch (IOException | NoSuchMethodException | InvocationTargetException | IllegalAccessException | InstantiationException e) {
            logger.error("MessagePackSerialize.parseObject.Exception, " + clazz, e);
        }
        return null;
    }

    @SuppressWarnings("unchecked")
    private static <T> T parseObject(MessageUnpacker unPacker, Class<T> clazz, Type[] type) throws IOException, NoSuchMethodException,
            IllegalAccessException, InvocationTargetException, InstantiationException {
        T tt = parseToClass(unPacker, clazz, type);
        if (tt != null) {
            return tt;
        }

        List<FieldAnnotation> fieldAnnotationList = getFiledAnnotation(clazz);
        Constructor<?> constructor = clazz.getDeclaredConstructor();
        constructor.setAccessible(true);
        T obj = (T) constructor.newInstance();
        for (FieldAnnotation fieldAnnotation : fieldAnnotationList) {
            Class typeClass = fieldAnnotation.field.getType();
            if (unPacker.tryUnpackNil() || !unPacker.hasNext()) {
                fieldAnnotation.field.set(obj, null);
                continue;
            }
            if (typeClass.isArray()) {
                fieldAnnotation.field.set(obj, parseToClass(unPacker, typeClass, null));
            } else if (List.class.isAssignableFrom(typeClass)) {
                Type[] types = ((ParameterizedType) fieldAnnotation.field.getGenericType()).getActualTypeArguments();
                if (types.length > 0) {
                    fieldAnnotation.field.set(obj, parseToList(unPacker, types));
                }
            } else if (Set.class.isAssignableFrom(typeClass)) {
                Type[] types = ((ParameterizedType) fieldAnnotation.field.getGenericType()).getActualTypeArguments();
                if (types.length > 0) {
                    fieldAnnotation.field.set(obj, parseToSet(unPacker, types));
                }
            } else if (typeClass.equals(Map.class)) {
                Type[] t = ((ParameterizedType) (fieldAnnotation.field.getGenericType())).getActualTypeArguments();
                fieldAnnotation.field.set(obj, parseToMap(unPacker, t));
            } else {
                if (typeClass.getName().equals(DataEnum.INT.clazz)) {
                    fieldAnnotation.field.set(obj, unPacker.unpackInt());
                } else if (typeClass.getName().equals(DataEnum.LONG.clazz)) {
                    fieldAnnotation.field.set(obj, unPacker.unpackLong());
                } else if (typeClass.getName().equals(DataEnum.SHORT.clazz)) {
                    fieldAnnotation.field.set(obj, unPacker.unpackShort());
                } else if (typeClass.getName().equals(DataEnum.FLOAT.clazz)) {
                    fieldAnnotation.field.set(obj, unPacker.unpackFloat());
                } else if (typeClass.getName().equals(DataEnum.DOUBLE.clazz)) {
                    fieldAnnotation.field.set(obj, unPacker.unpackDouble());
                } else if (typeClass.getName().equals(DataEnum.BYTE.clazz)) {
                    fieldAnnotation.field.set(obj, unPacker.unpackByte());
                } else if (typeClass.getName().equals(DataEnum.CHAR.clazz)) {
                    fieldAnnotation.field.set(obj, unPacker.unpackInt());
                } else if (typeClass.getName().equals(DataEnum.BOOLEAN.clazz)) {
                    fieldAnnotation.field.set(obj, unPacker.unpackBoolean());
                } else if (typeClass.getName().equals(DataEnum.STRING.clazz)) {
                    fieldAnnotation.field.set(obj, unPacker.unpackString());
                } else if ("[B".equals(typeClass.getName())) {
                    int byteLength = unPacker.unpackInt();
                    fieldAnnotation.field.set(obj, unPacker.readPayload(byteLength));
                } else {
                    logger.error("not support clazz:{}, typeClass:{}", clazz, typeClass);
                }
            }
        }
        return obj;
    }

    @SuppressWarnings("unchecked")
    private static Map<Object, Object> parseToMap(MessageUnpacker unPacker, Type[] types) throws IOException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
        if (!unPacker.hasNext() || unPacker.tryUnpackNil()) {
            return null;
        }
        int size = unPacker.unpackInt();
        Map<Object, Object> map = new HashMap<>(size);
        for (int i = 0; i < size; i++) {
            Object key = null;
            Object value = null;

            if (isBoxingClass(types[0])) {
                key = parseToBoxingData(unPacker, (Class) types[0]);
            } else if(types[0] instanceof Class && ((Class)types[0]).isArray()) {
                key = parseToArray(unPacker, (Class)types[0]);
            } else if(types[0] instanceof Class && !List.class.isAssignableFrom((Class)types[0]) && !Set.class.isAssignableFrom((Class)types[0]) && !Map.class.isAssignableFrom((Class)types[0]) ) {
                int subSize = unPacker.unpackInt();
                byte[] subBytes = unPacker.readPayload(subSize);
                key = parseSubObject(subBytes, (Class)types[0]);
            } else if (types[0] instanceof ParameterizedTypeImpl) {
                Class<?> clazz = ((ParameterizedTypeImpl) types[0]).getRawType();
                key = parseToClass(unPacker, clazz, ((ParameterizedTypeImpl) types[0]).getActualTypeArguments());
            } else if (types[1] instanceof ParameterizedType) {
                Class<?> clazz = (Class)((ParameterizedType) types[1]).getRawType();
                key = parseToClass(unPacker, clazz, ((ParameterizedType) types[1]).getActualTypeArguments());
            }
            if (isBoxingClass(types[1])) {
                value = parseToBoxingData(unPacker, (Class) types[1]);
            } else if(types[1] instanceof Class && ((Class)types[1]).isArray()) {
                value = parseToArray(unPacker, (Class)types[0]);
            } else if(types[1] instanceof Class && !List.class.isAssignableFrom((Class)types[1]) && !Set.class.isAssignableFrom((Class)types[1]) && !Map.class.isAssignableFrom((Class)types[1]) ) {
                int subSize = unPacker.unpackInt();
                byte[] subBytes = unPacker.readPayload(subSize);
                value = parseSubObject(subBytes, (Class)types[1]);
            } else if (types[1] instanceof ParameterizedTypeImpl) {
                Class<?> clazz = ((ParameterizedTypeImpl) types[1]).getRawType();
                value = parseToClass(unPacker, clazz, ((ParameterizedTypeImpl) types[1]).getActualTypeArguments());
            } else if (types[1] instanceof ParameterizedType) {
                Class<?> clazz = (Class)((ParameterizedType) types[1]).getRawType();
                value = parseToClass(unPacker, clazz, ((ParameterizedType) types[1]).getActualTypeArguments());
            }
            map.put(key, value);
        }
        return map;
    }

    @SuppressWarnings("unchecked")
    private static <T> T parseToArray(MessageUnpacker unPacker, Class<T> clazz) throws IOException {
        if(!unPacker.hasNext() || unPacker.tryUnpackNil()) {
            return null;
        }
        if (clazz.getName().equals(DataEnum.ARRAY_INT.clazz)) {
            int length = unPacker.unpackInt();
            int[] kk = new int[length];
            for (int i = 0; i < length; i++) {
                kk[i] = unPacker.unpackInt();
            }
            return (T) kk;
        } else if (clazz.getName().equals(DataEnum.ARRAY_INT_BOX.clazz)) {
            int length = unPacker.unpackInt();
            Integer[] kk = new Integer[length];
            for (int i = 0; i < length; i++) {
                kk[i] = unPacker.unpackInt();
            }
            return (T) kk;
        } else if (clazz.getName().equals(DataEnum.ARRAY_LONG.clazz)) {
            int length = unPacker.unpackInt();
            long[] kk = new long[length];
            for (int i = 0; i < length; i++) {
                kk[i] = unPacker.unpackLong();
            }
            return (T) kk;
        } else if (clazz.getName().equals(DataEnum.ARRAY_LONG_BOX.clazz)) {
            int length = unPacker.unpackInt();
            Long[] kk = new Long[length];
            for (int i = 0; i < length; i++) {
                kk[i] = unPacker.unpackLong();
            }
            return (T) kk;
        } else if (clazz.getName().equals(DataEnum.ARRAY_BYTE.clazz)) {
            int length = unPacker.unpackInt();
            return (T) unPacker.readPayload(length);
        } else if (clazz.getName().equals(DataEnum.ARRAY_BYTE_BOX.clazz)) {
            int length = unPacker.unpackInt();
            Byte[] kk = new Byte[length];
            for (int i = 0; i < length; i++) {
                kk[i] = unPacker.unpackByte();
            }
            return (T) kk;
        } else {
            throw new RuntimeException("not support Array.class " + clazz);
        }
    }

    @SuppressWarnings("unchecked")
    private static <T> T parseToClass(MessageUnpacker unPacker, Class<T> clazz, Type[] type) throws IOException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
        if (clazz.isArray()) {
            return parseToArray(unPacker, clazz);
        } else if(List.class.isAssignableFrom(clazz)) {
            return (T)parseToList(unPacker, type);
        } else if (Set.class.isAssignableFrom(clazz)) {
            return (T)parseToSet(unPacker, type);
        } else if (Map.class.isAssignableFrom(clazz)) {
            return (T)parseToMap(unPacker, type);
        } else if (isBoxingClass(clazz)) {
            return parseToBoxingData(unPacker, clazz);
        }
        return null;
    }

    private static Set parseToSet(MessageUnpacker unPacker, Type[] type) throws IOException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
        if(!unPacker.hasNext() || unPacker.tryUnpackNil()) {
            return null;
        }
        int size = unPacker.unpackInt();
        Set set = new HashSet(size);
        parseToCollection(unPacker, type, set, size);
        return set;
    }

    private static List parseToList(MessageUnpacker unPacker, Type[] type) throws IOException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
        if(!unPacker.hasNext() || unPacker.tryUnpackNil()) {
            return null;
        }
        int listSize = unPacker.unpackInt();
        List list = new ArrayList(listSize);
        parseToCollection(unPacker, type, list, listSize);
        return list;
    }

    @SuppressWarnings("unchecked")
    private static void parseToCollection(MessageUnpacker unPacker, Type[] type, Collection collection, int size) throws IOException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
        for (int i = 0; i < size; i++) {
            if (isBoxingClass(type[0])) {
                collection.add(parseToBoxingData(unPacker, (Class) type[0]));
            } else if(type[0] instanceof Class && ((Class)type[0]).isArray()) {
                collection.add(parseToArray(unPacker, (Class)type[0]));
            }else if(type[0] instanceof Class && !List.class.isAssignableFrom((Class)type[0]) && !Set.class.isAssignableFrom((Class)type[0]) && !Map.class.isAssignableFrom((Class)type[0]) ) {
                int subSize = unPacker.unpackInt();
                byte[] subBytes = unPacker.readPayload(subSize);
                collection.add(parseSubObject(subBytes, (Class)type[0]));
            } else if (type[0] instanceof ParameterizedTypeImpl) {
                Class<?> subSubClazz = ((ParameterizedTypeImpl) type[0]).getRawType();
                collection.add(parseToClass(unPacker, subSubClazz, ((ParameterizedTypeImpl) type[0]).getActualTypeArguments()));
            } else if (type[1] instanceof ParameterizedType) {
                Class<?> clazz = (Class)((ParameterizedType) type[0]).getRawType();
                collection.add(parseToClass(unPacker, clazz, ((ParameterizedType) type[0]).getActualTypeArguments()));
            }
        }
    }

    @SuppressWarnings("unchecked")
    private static <T> T parseToBoxingData(MessageUnpacker unPacker, Class<T> clazz) throws IOException {
        if (!unPacker.hasNext() || unPacker.tryUnpackNil()) {
            return null;
        }
        if (clazz.equals(Integer.class)) {
            return (T) new Integer(unPacker.unpackInt());
        } else if (clazz.equals(Long.class)) {
            return ((T) new Long(unPacker.unpackLong()));
        } else if (clazz.equals(Short.class)) {
            return ((T) new Short(unPacker.unpackShort()));
        } else if (clazz.equals(Float.class)) {
            return ((T) new Float(unPacker.unpackFloat()));
        } else if (clazz.equals(Double.class)) {
            return ((T) new Double(unPacker.unpackDouble()));
        } else if (clazz.equals(Byte.class)) {
            return ((T) new Byte(unPacker.unpackByte()));
        } else if (clazz.equals(Character.class)) {
            return ((T) new Character((char) unPacker.unpackInt()));
        } else if (clazz.equals(Boolean.class)) {
            return ((T) Boolean.valueOf(unPacker.unpackBoolean()));
        } else if ("[B".equals(clazz.getName())) {
            int byteLength = unPacker.unpackInt();
            return ((T) unPacker.readPayload(byteLength));
        } else if (clazz.equals(String.class)) {
            return ((T) unPacker.unpackString());
        } else {
            int byteLength = unPacker.unpackInt();
            byte[] tmpBytes = unPacker.readPayload(byteLength);
            return (parseObject(tmpBytes, clazz));
        }
    }


    private static List<FieldAnnotation> getFiledAnnotation(Class clazz) {
        List<FieldAnnotation> list = FIELD_WEAK_HASH_MAP.get(clazz);
        if (list != null) {
            return list;
        }
        Field[] fields = clazz.getDeclaredFields();
        if (fields == null || fields.length == 0) {
            throw new RuntimeException("MessagePackSerialize.getFiledAnnotation.field null. " + clazz);
        }
        List<FieldAnnotation> fieldAnnotationList = new ArrayList<>();
        for (Field field : fields) {
            Storage[] storageArray = field.getAnnotationsByType(Storage.class);
            if (storageArray != null && storageArray.length == 1) {
                int index = storageArray[0].index();
                field.setAccessible(true);
                fieldAnnotationList.add(new FieldAnnotation(index, field));
            }
        }
        if (fieldAnnotationList.size() == 0) {
            throw new RuntimeException("MessagePackSerialize.getFiledAnnotation.field.annotation null. " + clazz);
        }
        fieldAnnotationList.sort(Comparator.comparing(FieldAnnotation::getIndex));
        FIELD_WEAK_HASH_MAP.put(clazz, fieldAnnotationList);

        return fieldAnnotationList;
    }

    private static class FieldAnnotation {
        int index;
        Field field;

        FieldAnnotation(int index, Field field) {
            this.index = index;
            this.field = field;
        }

        public int getIndex() {
            return index;
        }
    }

    private enum DataEnum {
        INT("int"),
        LONG("long"),
        SHORT("short"),
        CHAR("char"),
        BOOLEAN("boolean"),
        BYTE("byte"),
        DOUBLE("double"),
        FLOAT("float"),
        STRING("java.lang.String"),
        ARRAY_INT("[I"),
        ARRAY_LONG("[J"),
        ARRAY_BYTE("[B"),

        ARRAY_INT_BOX("[Ljava.lang.Integer;"),
        ARRAY_LONG_BOX("[Ljava.lang.Long;"),
        ARRAY_BYTE_BOX("[Ljava.lang.Byte;"),;
        String clazz;

        DataEnum(String clazz) {
            this.clazz = clazz;
        }
    }


    private static byte[] zip(byte[] bytes) throws IOException {
        if (bytes == null) {
            return null;
        }
        byte[] result;
        if (bytes.length > MAX_LENGTH) {
            byte[] zipBytes = ZipUtil.compressByZlib(bytes, 0, bytes.length);
            result = new byte[zipBytes.length + 1];
            result[0] = 1;
            System.arraycopy(zipBytes, 0, result, 1, zipBytes.length);
        } else {
            result = new byte[bytes.length + 1];
            result[0] = 0;
            System.arraycopy(bytes, 0, result, 1, bytes.length);
        }
        return result;
    }

    private static byte[] unzip(byte[] bytes) throws IOException {
        if (bytes == null) {
            return null;
        }
        byte zip = bytes[0];
        if (zip == 1) {
            return ZipUtil.decompressByZlib(bytes, 1, bytes.length - 1);
        } else {
            byte[] tmp = new byte[bytes.length - 1];
            System.arraycopy(bytes, 1, tmp, 0, bytes.length - 1);
            return tmp;
        }
    }
}
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * MessagePack的序列化注解
 *
 * @author 天下武学
 * date 2020-07-02 19:26
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface Storage {
    int index() default 0;
}
import org.msgpack.core.MessageBufferPacker;
import org.msgpack.core.MessagePack;
import org.msgpack.core.MessageUnpacker;

import java.io.IOException;
import java.util.List;

/**
 * description: just for MessagePackSerialize
 *
 * @author 天下武学
 * date 2020-07-02 19:26
 **/
public class DemoTest {

    @Storage(index = 1)
    private int a;

    @Storage(index = 2)
    private long b;

    @Storage(index = 3)
    private short c;

    @Storage(index = 4)
    private String d;

    @Storage(index = 5)
    private byte []bytes;

    @Storage(index = 6)
    private List<Integer> list;

    public DemoTest() {

    }
    public DemoTest(Integer a, long b, short c, String d, byte []bytes, List<Integer> list) {
        this.a = a;
        this.b = b;
        this.c = c;
        this.d = d;
        this.bytes = bytes;
        this.list = list;
    }

    public Integer getA() {
        return a;
    }

    public long getB() {
        return b;
    }

    public short getC() {
        return c;
    }

    public String getD() {
        return d;
    }

    public byte[] getBytes() {
        return bytes;
    }

    public List<Integer> getList() {
        return list;
    }

    public byte[] toByte() throws IOException {
        MessageBufferPacker packer = MessagePack.newDefaultBufferPacker();
        packer.packInt(a);
        packer.packLong(b);
        packer.packShort(c);
        packer.packString(d);
        packer.packArrayHeader(this.bytes.length);
        packer.writePayload(bytes);
        packer.close();
        return packer.toByteArray();
    }

    public static DemoTest newInstance(byte[] bytes) throws IOException {
        MessageUnpacker unPacker = MessagePack.newDefaultUnpacker(bytes);
        DemoTest modelTest = new DemoTest();
        modelTest.a = unPacker.unpackInt();
        modelTest.b = unPacker.unpackLong();
        modelTest.c = unPacker.unpackShort();
        modelTest.d = unPacker.unpackString();
        int length = unPacker.unpackArrayHeader();
        modelTest.bytes = unPacker.readPayload(length);
        return modelTest;
    }
}
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.junit.Test;
import org.msgpack.core.MessageBufferPacker;
import org.msgpack.core.MessagePack;
import org.msgpack.core.MessageUnpacker;

import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.LongStream;

//@RunWith(SpringJUnit4ClassRunner.class)
public class MessagePackSerialTest {

    private void serial1(DemoTest model) throws IOException, IllegalAccessException, InvocationTargetException, InstantiationException {

//        System.out.println(JSONObject.toJSON(model));
        long start = System.currentTimeMillis();
        byte[] bytes = MessagePackSerialize.toBytes(model);
        long time1 = System.currentTimeMillis();

        DemoTest obj = MessagePackSerialize.parseObject(bytes, DemoTest.class);
        long time2 = System.currentTimeMillis();
//        System.out.println("time1 - start : " + (time1 - start));
//        System.out.println("time2 - time1 : " + (time2 - time1));
//        System.out.println(Arrays.toString(bytes));
//        System.out.println(JSONObject.toJSON(obj));
//
//        System.out.println("\n");
    }

    private void serial2(DemoTest model) throws IOException, IllegalAccessException, InvocationTargetException, InstantiationException {
        long time3 = System.currentTimeMillis();
        byte[] bytes2 = model.toByte();
        long time4 = System.currentTimeMillis();
        DemoTest obj2 = DemoTest.newInstance(bytes2);
        long time5 = System.currentTimeMillis();

//        System.out.println("time4 - time3 : " + (time4 - time3));
//        System.out.println("time5 - time4 : " + (time5 - time3));
//
//        System.out.println(JSONObject.toJSON(obj2));
//        System.out.println("\n\n\n");
    }

    @Test
    public void for1() throws InvocationTargetException, InstantiationException, IllegalAccessException, IOException {
        DemoTest model = new DemoTest(101, 30983745L, (short)45, "aslasd;lkfjalkjre\0f", new byte[]{1,3}, Arrays.asList(1, 7, 8));
        DemoTest model2 = new DemoTest(198713, 30457345L, (short)54, "aajerslkdjasd;lkfjalkjre\0f", new byte[]{1,3, 5, 8,1}, Arrays.asList(1, 7, 8, 101,12));
        serial1(model);
        long time1 = System.currentTimeMillis();
        for (int i = 0; i < 10000; i++) {
            serial1(model);
        }
        long time2 = System.currentTimeMillis();
        System.out.println("serial1 cost : " + (time2 - time1));

        serial2(model2);
        long time3 = System.currentTimeMillis();
        for (int i = 0; i < 10000; i++) {
            serial2(model2);
        }
        long time4 = System.currentTimeMillis();
        System.out.println("serial1 cost : " + (time4 - time3));
    }


    @Test
    public void objToBytes() {
        DemoTest model = new DemoTest(101, 30983745L, (short)45, "aslasd;lkfjalkjre\0f", new byte[]{1,3}, Arrays.asList(1, 7, 8));
        System.out.println(JSONObject.toJSON(model));
        byte[] bytes = MessagePackSerialize.toBytes(model);
        System.out.println(Arrays.toString(bytes));
        //[101, -50, 1, -40, -58, 65, 45, -77, 97, 115, 108, 97, 115, 100, 59, 108, 107, 102, 106, 97, 108, 107, 106, 114, 101, 0, 102, -110, 1, 3]

        //[101, -50, 1, -40, -58, 65, 45, -77, 97, 115, 108, 97, 115, 100, 59, 108, 107, 102, 106, 97, 108, 107, 106, 114, 101, 0, 102, -110, 1, 3, 3, 1, 7, 8]

        DemoTest model2 = MessagePackSerialize.parseObject(bytes, DemoTest.class);
        System.out.println(JSONObject.toJSON(model2));
    }


    @Test
    public void mapToBytes() {
        Map<Integer, DemoTest> map = new HashMap<>();
        for (int i = 0; i < 3; i++) {
            DemoTest model = new DemoTest(101 + i, 30983745L, (short)45, "aslasd;lkfjalkjre\0f", new byte[]{1,3}, Arrays.asList(1, 7, 8));
            map.put(i, model);
        }
        byte[] bytes = MessagePackSerialize.toBytes(map);
        System.out.println(Arrays.toString(bytes));
        //[-36, 0, 103, -125, 0, -36, 0, 30, 101, -50, 1, -40, -58, 65, 45, -77, 97, 115, 108, 97, 115, 100, 59, 108, 107, 102, 106, 97, 108, 107, 106, 114, 101, 0, 102, -110, 1, 3, 1, -36, 0, 30, 102, -50, 1, -40, -58, 65, 45, -77, 97, 115, 108, 97, 115, 100, 59, 108, 107, 102, 106, 97, 108, 107, 106, 114, 101, 0, 102, -110, 1, 3, 2, -36, 0, 30, 103, -50, 1, -40, -58, 65, 45, -77, 97, 115, 108, 97, 115, 100, 59, 108, 107, 102, 106, 97, 108, 107, 106, 114, 101, 0, 102, -110, 1, 3]
    }

    @Test
    public void testNull() {
        List<DemoTest> list = new ArrayList<>();
        for (int i = 0; i < 3; i++) {
            DemoTest model = new DemoTest(101 + i, 30983745L, (short)45, "aslasd;lkfjalkjre\0f", new byte[]{1,3}, Arrays.asList(1, 7, 8));
            list.add(model);
        }

        Map<String, Set<Short>> map = new HashMap<>();
        map.put("1", new HashSet<>());
        map.put("2", (IntStream.range(13, 15).boxed().map(Integer::shortValue).collect(Collectors.toSet())));

        DemoTest2 model = new DemoTest2();
        model.a =(null);
        model.b = (2L);
        model.c = ("123123");
        model.dd = (new Integer[]{33, 44});
        model.ee = map;
        model.ff = (IntStream.range(3, 5).boxed().collect(Collectors.toSet()));
        model.gg = (list);
        model.hh = new HashSet<>();
        byte[] bytes = MessagePackSerialize.toBytes(model);
        System.out.println(Arrays.toString(bytes));
        System.out.println(JSON.toJSONString(model));

        DemoTest2 model2 = MessagePackSerialize.parseObject(bytes, DemoTest2.class);
        System.out.println(JSON.toJSONString(model2));


        System.out.println("-----------------");
        System.out.println("-----------------");


        Set<Long> t1 = (LongStream.range(6, 8).boxed().collect(Collectors.toSet()));
        Set<Long> t2 = (LongStream.range(8, 10).boxed().collect(Collectors.toSet()));
        Set<Set<Long>> tt = new HashSet<>();
        tt.add(t1);
        tt.add(t2);
        model.hh = tt;
        model.gg = null;
        bytes = MessagePackSerialize.toBytes(model);
        System.out.println(Arrays.toString(bytes));
        System.out.println(JSON.toJSONString(model));

        model2 = MessagePackSerialize.parseObject(bytes, DemoTest2.class);
        System.out.println(JSON.toJSONString(model2));

        System.out.println("==================");
        System.out.println("==================");


        Set<Set<Set<Long>>> ttt = new HashSet<>();
        ttt.add(tt);
        model.iii = ttt;
        bytes = MessagePackSerialize.toBytes(model);
        System.out.println(Arrays.toString(bytes));
        System.out.println(JSON.toJSONString(model));

        model2 = MessagePackSerialize.parseObject(bytes, DemoTest2.class);
        System.out.println(JSON.toJSONString(model2));
    }

    @Data
    private static class DemoTest2 {

        @Storage(index = 1)
        private Integer a;

        @Storage(index = 2)
        private long b;

        @Storage(index = 3)
        private String c;

        @Storage(index = 4)
        private Integer[] dd;

        @Storage(index = 5)
        private Map<String, Set<Short>> ee;

        @Storage(index = 6)
        private Set<Integer> ff;

        @Storage(index = 7)
        private List<DemoTest> gg;

        @Storage(index = 8)
        private Set<Set<Long>> hh;

        @Storage(index = 9)
        private Set<Set<Set<Long>>> iii;

        @Storage(index = 10)
        private Map<String, Set<String>> jj;
    }

    @Test
    public void tt() {
        System.out.println((byte)138);
    }


    @Test
    public void test11212() {
        int type = 1;
        String jsonStr = "{\"ret\":1,\"data\":[{\"product_id\":3048,\"product_name\":\"西瓜 箱(6个)\",\"status\":true,\"format_list\":[{\"format_id\":3048,\"format_select_id\":null,\"product_id\":3048,\"is_supplier\":null,\"supplier_id\":null,\"unit_name\":\"\",\"unit_bili\":null,\"unit_sku_num\":6,\"sell_type\":1,\"pssu_id\":549701,\"psku_id\":535159,\"msku_id\":null,\"format_name\":\"箱\"}],\"text_label_list\":null,\"pic_label_list\":null,\"product_desc\":\"西瓜 箱(6个)\",\"product_short_desc\":\"\",\"thumb_img\":\"https://img-oss.stage.yunshanmeicai.com/mjyx/product/ec830693d86b65fd51968853a5b045344413aca5.jpg\",\"loop_pics\":[\"https://img-oss.stage.yunshanmeicai.com/mjyx/product/ec830693d86b65fd51968853a5b045344413aca5.jpg\"],\"promises\":[{\"sort\":0,\"value\":\"免运费\"},{\"sort\":0,\"value\":\"次日达\"},{\"sort\":0,\"value\":\"自提\"}],\"detail_pics\":[{\"img_url\":\"https://img-oss.stage.yunshanmeicai.com/mjyx/product/ec830693d86b65fd51968853a5b045344413aca5.jpg\",\"thumbnail_url\":\"https://img-oss.stage.yunshanmeicai.com/mjyx/product/ec830693d86b65fd51968853a5b045344413aca5.jpg\",\"width\":480,\"height\":259},{\"img_url\":\"https://img-oss.stage.yunshanmeicai.com/mjyx/product/80af38bf0872c401768465dda2bc91848c87bbec.jpg\",\"thumbnail_url\":\"https://img-oss.stage.yunshanmeicai.com/mjyx/product/80af38bf0872c401768465dda2bc91848c87bbec.jpg\",\"width\":268,\"height\":266},{\"img_url\":\"https://img-oss.stage.yunshanmeicai.com/mjyx/product/be74f8ef61be371ff422b5b08b753963edb816b3.jpg\",\"thumbnail_url\":\"https://img-oss.stage.yunshanmeicai.com/mjyx/product/be74f8ef61be371ff422b5b08b753963edb816b3.jpg\",\"width\":180,\"height\":140}],\"pop_id\":1,\"source_type\":4,\"delivery_way\":null,\"goods_type\":1,\"sclass1_id\":2010,\"sclass2_id\":2010037,\"valid_start_time\":null,\"valid_end_time\":null}]}";
        if (StringUtils.isEmpty(jsonStr)){
            System.out.println("error. 1");
        }
        JSONObject json = JSONObject.parseObject(jsonStr);
        if (!"1".equals(json.getString("ret"))){
            System.out.println("error. 2");
        }
        JSONArray data = json.getJSONArray("data");
        if (data == null || data.size() == 0){
            System.out.println("error. 3");
        }
        JSONArray ret = new JSONArray();
        for(int i=0;i<data.size();i++){
            JSONObject job = data.getJSONObject(i);
            //类型0是下架,1是上架 --上架需要过滤失效商品
            if (type == 1 && !job.getBoolean("status")){
                continue;
            }
            String class1Name = null;
            String class2Name = null;
            job.put("class_name", class1Name + "-" + class2Name);
            ret.add(job);
        }
        System.out.println(ret.toJSONString());
    }

    @Test
    public void array() {
        DemoTest3 model = new DemoTest3();
        System.out.println(JSON.toJSONString(model));

        byte[] bytes;

        bytes = MessagePackSerialize.toBytes(model);
        System.out.println(Arrays.toString(bytes));

        model = MessagePackSerialize.parseObject(bytes, DemoTest3.class);
        System.out.println(JSON.toJSONString(model));
        if(model == null) {
            return;
        }

        System.out.println("-------------");

        model.a = new int[]{1, 3, 5};
        model.b = new long[]{11, 31, 5111};
        model.c = new byte[]{-51, 19, -9};
        System.out.println(JSON.toJSONString(model));

        bytes = MessagePackSerialize.toBytes(model);
        System.out.println(Arrays.toString(bytes));

        model = MessagePackSerialize.parseObject(bytes, DemoTest3.class);
        System.out.println(JSON.toJSONString(model));
        if(model == null) {
            return;
        }
        System.out.println("=================");

        model.a = null;
        model.b = null;
        model.c = null;

        model.aa = new Integer[]{1, 3, 5};
        model.bb = new Long[]{11L, 31L, 5111L};
        model.cc = new Byte[]{-51, 19, -9};

        System.out.println(JSON.toJSONString(model));

        bytes = MessagePackSerialize.toBytes(model);
        System.out.println(Arrays.toString(bytes));

        model = MessagePackSerialize.parseObject(bytes, DemoTest3.class);
        System.out.println(JSON.toJSONString(model));

    }

    @Data
    private static class DemoTest3 {
        @Storage(index = 1)
        private int[] a;
        @Storage(index = 2)
        private long[] b;
        @Storage(index = 3)
        private byte[] c;

        @Storage(index = 4)
        private Integer[] aa;
        @Storage(index = 5)
        private Long[] bb;
        @Storage(index = 6)
        private Byte[] cc;

    }

    @Test
    public void tryNil() {
        byte[] bytes = null;
        try (MessageBufferPacker packer = MessagePack.newDefaultBufferPacker()) {
            packer.packNil();
            packer.packNil();
            packer.packByte((byte)-51);
            bytes = packer.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println(Arrays.toString(bytes));

        try (MessageUnpacker unPacker = MessagePack.newDefaultUnpacker(bytes)) {
            unPacker.tryUnpackNil();
            unPacker.unpackNil();
            unPacker.tryUnpackNil();
            System.out.println("int = " + unPacker.unpackByte());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void testSys(){
        Map<String, List<Integer>> map = new HashMap<>();
        List<Integer> list = IntStream.range(0, 10).boxed().collect(Collectors.toList());
        map.put("1", list);
        System.out.println(map.toString());

    }
}

 

posted @ 2020-12-15 10:07  天下武学2  阅读(135)  评论(0)    收藏  举报