序列化框架-msgpack

官网

https://msgpack.org/

It's like JSON.but fast and small.

说明

msg-pack-info.png

MessagePack 是一个高效的二进制序列化格式。它让你像JSON一样可以在各种语言之间交换数据。但是它比JSON更快、更小。小的整数会被编码成一个字节,短的字符串仅仅只需要比它的长度多一字节的大小。

原有json长度:27 byte
msgPack长度:18 byte

压缩原理

官方说明

布尔

bool 值可以用1byte表示

false:
+--------+
|  0xc2  |
+--------+

true:
+--------+
|  0xc3  |
+--------+

无长度

第一个字节特定标识

int 8 stores a 8-bit signed integer
+--------+--------+
|  0xd0  |ZZZZZZZZ|
+--------+--------+

int 16 stores a 16-bit big-endian signed integer
+--------+--------+--------+
|  0xd1  |ZZZZZZZZ|ZZZZZZZZ|
+--------+--------+--------+

int 32 stores a 32-bit big-endian signed integer
+--------+--------+--------+--------+--------+
|  0xd2  |ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|
+--------+--------+--------+--------+--------+

int 64 stores a 64-bit big-endian signed integer
+--------+--------+--------+--------+--------+--------+--------+--------+--------+
|  0xd3  |ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|
+--------+--------+--------+--------+--------+--------+--------+--------+--------+

不定长

主要是字符串、数组、二进制数据等

fixstr stores a byte array whose length is upto 31 bytes:
+--------+========+
|101XXXXX|  data  |
+--------+========+

str 8 stores a byte array whose length is upto (2^8)-1 bytes:
+--------+--------+========+
|  0xd9  |YYYYYYYY|  data  |
+--------+--------+========+

str 16 stores a byte array whose length is upto (2^16)-1 bytes:
+--------+--------+--------+========+
|  0xda  |ZZZZZZZZ|ZZZZZZZZ|  data  |
+--------+--------+--------+========+

str 32 stores a byte array whose length is upto (2^32)-1 bytes:
+--------+--------+--------+--------+--------+========+
|  0xdb  |AAAAAAAA|AAAAAAAA|AAAAAAAA|AAAAAAAA|  data  |
+--------+--------+--------+--------+--------+========+

高级结构

MAP结构

fixmap stores a map whose length is upto 15 elements
+--------+~~~~~~~~~~~~~~~~~+
|1000XXXX|   N*2 objects   |
+--------+~~~~~~~~~~~~~~~~~+

map 16 stores a map whose length is upto (2^16)-1 elements
+--------+--------+--------+~~~~~~~~~~~~~~~~~+
|  0xde  |YYYYYYYY|YYYYYYYY|   N*2 objects   |
+--------+--------+--------+~~~~~~~~~~~~~~~~~+

map 32 stores a map whose length is upto (2^32)-1 elements
+--------+--------+--------+--------+--------+~~~~~~~~~~~~~~~~~+
|  0xdf  |ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|   N*2 objects   |
+--------+--------+--------+--------+--------+~~~~~~~~~~~~~~~~~+

where
* XXXX is a 4-bit unsigned integer which represents N
* YYYYYYYY_YYYYYYYY is a 16-bit big-endian unsigned integer which represents N
* ZZZZZZZZ_ZZZZZZZZ_ZZZZZZZZ_ZZZZZZZZ is a 32-bit big-endian unsigned integer which represents N
* N is the size of a map
* odd elements in objects are keys of a map
* the next element of a key is its associated value

使用

导入包

repositories {
    mavenCentral()
}

dependencies {
    compile 'org.msgpack:msgpack-core:(version)'
}

数据打包

        try {
            MessageBufferPacker packer = MessagePack.newDefaultBufferPacker();
            packer
                .packInt(1)
                .packString("leo");
            // pack arrays
            int[] arr = new int[] {3, 5, 1, 0, -1, 255};
            packer.packArrayHeader(arr.length);
            for (int v : arr) {
                packer.packInt(v);
            }
            // pack map (key -> value) elements
            // the number of (key, value) pairs
            packer.packMapHeader(2);
            // Put "apple" -> 1
            packer.packString("apple");
            packer.packInt(1);
            // Put "banana" -> 2
            packer.packString("banana");
            packer.packInt(2);

            // pack binary data
            byte[] ba = new byte[] {1, 2, 3, 4};
            packer.packBinaryHeader(ba.length);
            packer.writePayload(ba);

            packer.close();

        } catch (IOException e) {

        }

如何对上面的数据解包呢

            MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(packer.toMessageBuffer().array());
            int id = unpacker.unpackInt();
            String name = unpacker.unpackString();
            System.out.print(id);
            System.out.print(name);
            int numPhones = unpacker.unpackArrayHeader();
            String[] phones = new String[numPhones];
            for (int i = 0; i < numPhones; ++i) {
                phones[i] = unpacker.unpackString();
            }
            int maplen = unpacker.unpackMapHeader();
            for (int j = 0; j < maplen; j++) {
                unpacker.unpackString();
                unpacker.unpackInt();
            }
            unpacker.close();

打包POJO

官方推荐使用 msgpack-jackson

导包

dependencies {
    compile 'org.msgpack:jackson-dataformat-msgpack:0.8.20'
}

实体类

    public static class MyMessage implements Serializable {

        public String name;
        public double version;

        public MyMessage(String name, double version) {
            this.name = name;
            this.version = version;
        }

        public MyMessage(){}
    }

按照官方文档写打包/解包代码

            ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory());
            MyMessage myMessage = new MyMessage("remer", 1111);
            byte[] bytes = objectMapper.writeValueAsBytes(myMessage);

            MyMessage deserialized = objectMapper.readValue(bytes, MyMessage.class);
            System.out.print(deserialized.name);

结论

  1. MsgPack产生的数据更小,从而在数据传输过程中网络压力更小
  2. MsgPack兼容性差,必须按照顺序保存字段
  3. MsgPack是二进制序列化格式,兼容跨语言

参考

msgpack
Quick Start msgpack
msgpack-jackson
Java JSON Tutorial
msgpack简介和使用
MsgPack是何方神圣

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容