zoukankan      html  css  js  c++  java
  • MessagePack枚举类的反序列化报错:Caused by: javassist.CannotCompileException: [source error] no such constructor: com.example..

    问题1:

    反序列化的枚举类:

    @Message
    public enum EnumClassd {
        Unknown   (0);
        @Getter
        @Setter
        private Integer code;
        EnumClassd(Integer code) {
            this.code = code;
        }
    
    }

    MessagePack反序列化上述枚举类时报错:

    org.msgpack.MessageTypeException: org.msgpack.template.builder.TemplateBuildException: Cannot compile: 
    {
      if (!$3 && $1.trySkipNil()) {
        return null;
      }
      com.example.EnumClass _$$_t;
      if ($2 == null) {
        _$$_t = new com.example.EnumClass();
      } else {
        _$$_t = (com.example.EnumClass) $2;
      }
      $1.readArrayBegin();
      if ($1.trySkipNil()) {  } else {
        org.msgpack.template.builder.DefaultBuildContext.readPrivateField($1, _$$_t, com.example.EnumClass.class, "code", templates[0]);
      }
      $1.readArrayEnd();
      return _$$_t;
    }
    
    
        at org.msgpack.template.TemplateRegistry.buildAndRegister(TemplateRegistry.java:575)
        at org.msgpack.template.TemplateRegistry.lookupAfterBuilding(TemplateRegistry.java:472)
        at org.msgpack.template.TemplateRegistry.lookup(TemplateRegistry.java:251)
        at org.msgpack.template.builder.JavassistTemplateBuilder.toTemplate(JavassistTemplateBuilder.java:129)
        at org.msgpack.template.builder.JavassistTemplateBuilder.buildTemplate(JavassistTemplateBuilder.java:117)
        at org.msgpack.template.builder.AbstractTemplateBuilder.buildTemplate(AbstractTemplateBuilder.java:61)
        at org.msgpack.template.TemplateRegistry.buildAndRegister(TemplateRegistry.java:562)
        at org.msgpack.template.TemplateRegistry.lookupAfterBuilding(TemplateRegistry.java:472)
        at org.msgpack.template.TemplateRegistry.lookup(TemplateRegistry.java:251)
        at org.msgpack.template.TemplateRegistry.lookupGenericTypeImpl0(TemplateRegistry.java:320)
        at org.msgpack.template.TemplateRegistry.lookupGenericTypeImpl(TemplateRegistry.java:308)
        at org.msgpack.template.TemplateRegistry.lookupGenericType(TemplateRegistry.java:280)
        at org.msgpack.template.TemplateRegistry.lookup(TemplateRegistry.java:205)
        at org.msgpack.template.builder.JavassistTemplateBuilder.toTemplate(JavassistTemplateBuilder.java:129)
        at org.msgpack.template.builder.JavassistTemplateBuilder.buildTemplate(JavassistTemplateBuilder.java:117)
        at org.msgpack.template.builder.AbstractTemplateBuilder.buildTemplate(AbstractTemplateBuilder.java:61)
        at org.msgpack.template.TemplateRegistry.buildAndRegister(TemplateRegistry.java:562)
        at org.msgpack.template.TemplateRegistry.lookupAfterBuilding(TemplateRegistry.java:472)
        at org.msgpack.template.TemplateRegistry.lookup(TemplateRegistry.java:251)
        at org.msgpack.MessagePack.read(MessagePack.java:370)
        at com.example.jenkinscodehubtest.util.OsvfUtil.ReadNextBlock(OsvfUtil.java:61)
        at com.example.jenkinscodehubtest.JenkinsCodehubTestApplicationTests.deal(JenkinsCodehubTestApplicationTests.java:46)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:688)
        at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
        at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
        at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
        at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
        at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
        at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
        at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
        at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
        at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
        at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
        at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
        at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
        at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:210)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:206)
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:131)
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:65)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
        at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
        at java.util.ArrayList.forEach(ArrayList.java:1249)
        at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
        at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
        at java.util.ArrayList.forEach(ArrayList.java:1249)
        at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
        at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
        at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
        at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
        at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
        at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:108)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
        at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
        at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:96)
        at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:75)
        at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
        at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
        at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:220)
        at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:53)
    Caused by: org.msgpack.template.builder.TemplateBuildException: Cannot compile: 
    {
      if (!$3 && $1.trySkipNil()) {
        return null;
      }
      com.example.EnumClass _$$_t;
      if ($2 == null) {
        _$$_t = new com.example.EnumClass();
      } else {
        _$$_t = (com.example.EnumClass) $2;
      }
      $1.readArrayBegin();
      if ($1.trySkipNil()) {  } else {
        org.msgpack.template.builder.DefaultBuildContext.readPrivateField($1, _$$_t, com.example.EnumClass.class, "code", templates[0]);
      }
      $1.readArrayEnd();
      return _$$_t;
    }
    
        at org.msgpack.template.builder.BuildContext.build(BuildContext.java:73)
        at org.msgpack.template.builder.DefaultBuildContext.buildTemplate(DefaultBuildContext.java:56)
        at org.msgpack.template.builder.JavassistTemplateBuilder.buildTemplate(JavassistTemplateBuilder.java:119)
        at org.msgpack.template.builder.AbstractTemplateBuilder.buildTemplate(AbstractTemplateBuilder.java:61)
        at org.msgpack.template.TemplateRegistry.buildAndRegister(TemplateRegistry.java:562)
        ... 86 more
    Caused by: javassist.CannotCompileException: [source error] no such constructor: com.example.EnumClass
        at javassist.CtBehavior.setBody(CtBehavior.java:446)
        at javassist.CtBehavior.setBody(CtBehavior.java:412)
        at javassist.CtNewMethod.make(CtNewMethod.java:138)
        at org.msgpack.template.builder.BuildContext.buildReadMethod(BuildContext.java:144)
        at org.msgpack.template.builder.BuildContext.build(BuildContext.java:65)
        ... 90 more
    Caused by: compile error: no such constructor: com.example.EnumClass
        at javassist.compiler.MemberCodeGen.atMethodCallCore2(MemberCodeGen.java:593)
        at javassist.compiler.MemberCodeGen.atMethodCallCore(MemberCodeGen.java:575)
        at javassist.compiler.MemberCodeGen.atNewExpr(MemberCodeGen.java:302)
        at javassist.compiler.ast.NewExpr.accept(NewExpr.java:73)
        at javassist.compiler.CodeGen.atAssignCore(CodeGen.java:860)
        at javassist.compiler.CodeGen.atVariableAssign(CodeGen.java:793)
        at javassist.compiler.CodeGen.atAssignExpr(CodeGen.java:747)
        at javassist.compiler.CodeGen.atStmnt(CodeGen.java:332)
        at javassist.compiler.ast.Stmnt.accept(Stmnt.java:50)
        at javassist.compiler.CodeGen.atStmnt(CodeGen.java:351)
        at javassist.compiler.ast.Stmnt.accept(Stmnt.java:50)
        at javassist.compiler.CodeGen.atIfStmnt(CodeGen.java:391)
        at javassist.compiler.CodeGen.atStmnt(CodeGen.java:355)
        at javassist.compiler.ast.Stmnt.accept(Stmnt.java:50)
        at javassist.compiler.CodeGen.atStmnt(CodeGen.java:351)
        at javassist.compiler.ast.Stmnt.accept(Stmnt.java:50)
        at javassist.compiler.CodeGen.atMethodBody(CodeGen.java:292)
        at javassist.compiler.Javac.compileBody(Javac.java:223)
        at javassist.CtBehavior.setBody(CtBehavior.java:438)
        ... 94 more
    
    Disconnected from the target VM, address: '127.0.0.1:54789', transport: 'socket'
    
    Process finished with exit code -1

    解决方法:

    将注解@Message改为注解@MessagePackOrdinalEnum即可解决(https://github.com/msgpack/msgpack/issues/66)

    问题2:

    Exception in thread "main" org.msgpack.MessageTypeException: Expected raw value, but got boolean
        at org.msgpack.unpacker.Accept.acceptBoolean(Accept.java:33)
        at org.msgpack.unpacker.MessagePackUnpacker.readOneWithoutStackLarge(MessagePackUnpacker.java:154)
        at org.msgpack.unpacker.MessagePackUnpacker.readOneWithoutStack(MessagePackUnpacker.java:139)
        at org.msgpack.unpacker.MessagePackUnpacker.readOne(MessagePackUnpacker.java:73)
        at org.msgpack.unpacker.MessagePackUnpacker.readString(MessagePackUnpacker.java:502)
        at org.msgpack.template.StringTemplate.read(StringTemplate.java:46)
        at org.msgpack.template.StringTemplate.read(StringTemplate.java:25)
        at org.msgpack.template.AbstractTemplate.read(AbstractTemplate.java:31)
        at com.my.msgpack.SimpleMessagePackPractice$MyMessage2_$$_Template_1305193908_1.read(SimpleMessagePackPractice$MyMessage2_$$_Template_1305193908_1.java)
        at org.msgpack.template.AbstractTemplate.read(AbstractTemplate.java:31)
        at org.msgpack.MessagePack.read(MessagePack.java:388)
        at org.msgpack.MessagePack.read(MessagePack.java:371)
        at com.my.msgpack.SimpleMessagePackPractice.main(SimpleMessagePackPractice.java:61)

     该报错是因为MessagePack序列化的结果中只包含了value,而不包含key。因而在进行反序列化需要保证类中属性的顺序必须保证完全一致,否则就会出错:

    如果两个属性的类型一致,可以反序列化,但是值发生错乱。
    如果两个属性的类型不一致,会抛出类型不匹配异常。
    因此解决方法是报错序列化和反序列化的对象顺序类型保持一致。
     
     
    MessagePack详情见下文:

    一、MessagePack是什么

    先看官方的定义:MessagePack是一种高效的二进制序列化格式。它允许您像JSON一样在多个语言之间交换数据。但是,它更快并且更小。

    从官方定义中,可以有如下的结论:

    1. MessagePack是一个二进制序列化格式,因而它序列化的结果可以在多个语言间进行数据的交换。

    2. 从性能上讲,它要比json的序列化格式要好。

    3. 从结果大小上讲,它要比json的序列化结果要小。

    但是官方并没有提MessagePack和google pb的对比,实际上从空间和时间两个方面对比,pb均要优于MessagePack,但pb相对MessagePack 的缺点是支持的语言种类比较少,需要编写专门的 .proto文件,使用上没有MessagePack方便。

    二、MessagePack的主要概念

     

    2.1 type system

    类型体系是MessagePack的基础,也是MessagePack在序列化后比json占用空间小的关键。当前包含的type有如下几类:
    • Integer represents an integer
    • Nil represents nil
    • Boolean represents true or false
    • Float represents a IEEE 754 double precision floating point number including NaN and Infinity
    • Raw
      • String extending Raw type represents a UTF-8 string
      • Binary extending Raw type represents a byte array
    • Array represents a sequence of objects
    • Map represents key-value pairs of objects
    • Extension represents a tuple of type information and a byte array where type information is an integer whose meaning is defined by applications or MessagePack specification
      • Timestamp represents an instantaneous point on the time-line in the world that is independent from time zones or calendars. Maximum precision is nanoseconds.
     
    这个类型体系将我们在代码开发中用到的数据格式进行了映射,并且通过Extension这个类型给使用者留出了自由扩充的空间,但由于表示形式的限制,当前Extension最多有127个。
     
    每一种类型能够表示的范围可以查看MessagePack规范中的Limitation部分和Extension types部分。

    2.2 formats

    在MessagePack中一个value的组成格式是这样的:类型[长度][data]。下面列出几个示例,详细完整的描述请看附录中的MessagePack规范。
     

    2.2.1常量型

    比如对于null、true、false这三个值,在MessagePack会被固定的映射为如下的值。
    format name
    first byte (in binary)
    first byte (in hex)
    nil
    11000000
    0xc0
    false
    11000010
    0xc2
    true
    11000011
    0xc3

    2.2.2 int型(包含有符号整数和无符号整数)

     
    示例如下 
    • 0xcc表示当前的值的类型是无符号整数并且长度不超过8个bit,具体的值内容需要通过后续8个bit位的内容来计算
    • 0xcd表示当前的值的类型是无符号整数并且长度不超过16个bit,具体的值内容需要通过后续16个bit位的内容来计算
    • 0xd0表示当前的值的类型是有符号整数并且长度不超过8个bit,具体的值内容需要通过后续8个bit位的内容来计算
    • 0xd1表示当前的值的类型是有符号整数并且长度不超过16个bit,具体的值内容需要通过后续16个bit位的内容来计算
    uint 8 stores a 8-bit unsigned integer  
    +--------+--------+
    |  0xcc  |ZZZZZZZZ|
    +--------+--------+
    
    uint 16 stores a 16-bit big-endian unsigned integer
    +--------+--------+--------+
    |  0xcd  |ZZZZZZZZ|ZZZZZZZZ|
    +--------+--------+--------+
    
    int 8 stores a 8-bit signed integer
    +--------+--------+
    |  0xd0  |ZZZZZZZZ|
    +--------+--------+
    
    int 16 stores a 16-bit big-endian signed integer
    +--------+--------+--------+
    |  0xd1  |ZZZZZZZZ|ZZZZZZZZ|
    +--------+--------+--------+

    2.2.3 字符串 

    • 0xd9表示当前的值的类型是字符串并且长度不超过(2^8)-1个bytes ,具体的长度需要通过后续8个bit位的内容来计算,字符串的具体内容是后续长度的byte所表示的内容
    • 0xda表示当前的值的类型是字符串并且长度不超过(2^16)-1个bytes ,具体的长度需要通过后续16个bit位的内容来计算,字符串的具体内容是后续长度的byte所表示的内容
    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  |
    +--------+--------+--------+========+

    2.2.4 数组 

    • 0xdc表示当前的值的类型是数组并且长度不超过(2^16)-1个元素 ,具体的长度需要通过后续16个bit位(两个byte)的内容来计算,计算出来的值就是数组元素的个数
    • 0xdd表示当前的值的类型是数组并且长度不超过(2^32)-1个元素 ,具体的长度需要通过后续32个bit位(4个byte)的内容来计算,计算出来的值就是数组元素的个数
    array 16 stores an array whose length is upto (2^16)-1 elements:
    +--------+--------+--------+~~~~~~~~~~~~~~~~~+
    |  0xdc  |YYYYYYYY|YYYYYYYY|    N objects    |
    +--------+--------+--------+~~~~~~~~~~~~~~~~~+
    
    array 32 stores an array whose length is upto (2^32)-1 elements:
    +--------+--------+--------+--------+--------+~~~~~~~~~~~~~~~~~+
    |  0xdd  |ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|ZZZZZZZZ|    N objects    |
    +--------+--------+--------+--------+--------+~~~~~~~~~~~~~~~~~+

    2.2.5 小结

    2.3 Serialization:type to format conversion

     
    source types
    output format
    Integer
    int format family (positive fixint, negative fixint, int 8/16/32/64 or uint 8/16/32/64)
    Nil
    nil
    Boolean
    bool format family (false or true)
    Float
    float format family (float 32/64)
    String
    str format family (fixstr or str 8/16/32)
    Binary
    bin format family (bin 8/16/32)
    Array
    array format family (fixarray or array 16/32)
    Map
    map format family (fixmap or map 16/32)
    Extension
    ext format family (fixext or ext 8/16/32)
    If an object can be represented in multiple possible output formats, serializers SHOULD use the format which represents the data in the smallest number of bytes.

    2.4 Deserialization: format to type conversion

    source formats
    output type
    positive fixint, negative fixint, int 8/16/32/64 and uint 8/16/32/64
    Integer
    nil
    Nil
    false and true
    Boolean
    float 32/64
    Float
    fixstr and str 8/16/32
    String
    bin 8/16/32
    Binary
    fixarray and array 16/32
    Array
    fixmap map 16/32
    Map
    fixext and ext 8/16/32
    Extension

    三、为什么MessagePack比json序列化使用的字节流更少 

    3.1 直观对比

    可以通过下图的两张图简单进行下对比,第一张图是同一个数据类型的内容用json和messagepack序列化的结果。

     从第二张图可以明显看到messagepack要比json占用的空间更少。

    3.2 序列化结果只有value且value进行了专属映射

     这张图是MessagePack官网上的,用来进行json和MessagePack序列化结果的对比,实际情况是否确实如此呢?

    我本地使用的msgpack-0.6.12版本。
    代码如下:
    public class MessagePackSerializationCompareJson {
    
        @Message // Annotation
        public static class MyMessage {
            // public fields are serialized.
            public boolean compact;
            public int schema;
            
            public  String toString() {
                return "compact:"+compact+";schema:"+schema;
            }
    
        }
        /**
         * 
         * @param args
         * @throws IOException 
         */
        public static void main(String[] args) throws IOException {
          //初始化一个对象
            MyMessage src = new MyMessage();
            src.compact = true;
            src.schema=0;
            
          //利用MessagePack进行序列化
            MessagePack msgpack = new MessagePack();
            // Serialize
            byte[] bytes = msgpack.write(src);
            System.out.println("msgpack result length:"+bytes.length);
            
            //利用json进行序列化
            String jsonResult = JSONObject.toJSON(src).toString();
            System.out.println("json result length:"+jsonResult.getBytes().length);
            
        }
    
    }

    运行结果如下:

    json result length:27
    msgpack result length:3

    json序列化的结果是27,和官网图片中的结果相同。但MessagePack的序列化结果是3,要比官网中的数字小很多。
    按照上面图片的解释应当是:
    • 第一个byte是82,表示序列化后的结果有两个元素
    • 第二个byte是c3,表示第一个元素的值是true
    • 第三个byte是00,表示第二个元素的值是0
     
    为了验证我们的推测,我们可以在MyMessage类中再添加一个boolean类型的属性,但不给这个属性赋值,按照java的规范,这个属性的值就是false,按照MessagePack的规范,就会被转为一个byte的c2,这样msgpack序列化后的长度值就是4.  而json序列化的增加值要增加不少,是属性名称的长度+5(false的长度)+4(要增加两个双引号,一个逗号,一个冒号),如果属性名称长度是4,则一共会增加13个byte,总长度就是40.
    public class MessagePackSerializationCompareJson {
    
        @Message // Annotation
        public static class MyMessage {
            // public fields are serialized.
            public boolean compact;
            public int schema;
            public boolean link;
            
            
            public  String toString() {
                return "compact:"+compact+";schema:"+schema+";link:"+link;
            }
    
        }
        /**
         * 
         * @param args
         * @throws IOException 
         */
        public static void main(String[] args) throws IOException {
          //初始化一个对象
            MyMessage src = new MyMessage();
            src.compact = true;
            src.schema=0;
            
          //利用json进行序列化
            String jsonResult = JSONObject.toJSON(src).toString();
            System.out.println("json result length:"+jsonResult.getBytes().length);
            
          //利用MessagePack进行序列化
            MessagePack msgpack = new MessagePack();
            // Serialize
            byte[] bytes = msgpack.write(src);
            System.out.println("msgpack result length:"+bytes.length);
            
        }
    
    }

    上面代码的执行的结果也符合猜测:

    json result length:40
    msgpack result length:4

    从这个数字上看,MessagePack明显优于json,特别是在属性多的情况下差距会更大。即使json中把key去掉,序列化后的结果也要比MessagePack占用的空间大。
     

    3.2 序列化对象的属性顺序不能变动

    3.1分析了MessagePack序列化的结果中只包含了value,而不包含key。因而在进行反序列化需要保证类中属性的顺序必须保证完全一致,否则就会出错:
    如果两个属性的类型一致,可以反序列化,但是值发生错乱。
    如果两个属性的类型不一致,会抛出类型不匹配异常。
     

    3.2.1 顺序不同,类型相同

    public class SimpleMessagePackPractice {
    
        @Message // Annotation
        public static class MyMessage {
            // public fields are serialized.
            public boolean compact;
            public boolean link;
    
            public String toString() {
                return "link:" + link + ";compact:" + compact;
            }
        }
    
        @Message // Annotation
        public static class MyMessage2 {
            // public fields are serialized.
            public boolean link;
            public boolean compact;
    
            public String toString() {
                return "link:" + link + ";compact:" + compact;
            }
        }
    
        /**
         * 
         * @param args
         * @throws IOException 
         */
        public static void main(String[] args) throws IOException {
    
            //初始化一个对象
            MyMessage src = new MyMessage();
            src.compact = true;
            src.link = false;
    
            //利用MessagePack进行序列化
            MessagePack msgpack = new MessagePack();
            // Serialize
            byte[] bytes = msgpack.write(src);
    
            //利用MessagePack进行反序列化
            MyMessage2 dst = msgpack.read(bytes, MyMessage2.class);
            System.out.println("msgpack 原始数据:" + src);
            System.out.println("msgpack 反序列化:" + dst);
            
            
        }
    
    }

    上述代码的执行结果如下:

    msgpack 原始数据:link:false;compact:true
    msgpack 反序列化:link:true;compact:false

    3.2.1 顺序不同,类型不同

    public class SimpleMessagePackPractice {
    
        @Message // Annotation
        public static class MyMessage {
            // public fields are serialized.
            public boolean compact;
            public String link;
    
            public String toString() {
                return "link:" + link + ";compact:" + compact;
            }
        }
    
        @Message // Annotation
        public static class MyMessage2 {
            // public fields are serialized.
            public String link;
            public boolean compact;
    
            public String toString() {
                return "link:" + link + ";compact:" + compact;
            }
        }
    
        /**
         * 
         * @param args
         * @throws IOException 
         */
        public static void main(String[] args) throws IOException {
    
            //初始化一个对象
            MyMessage src = new MyMessage();
            src.compact = true;
            src.link = "www.baidu.com";
    
            //利用MessagePack进行序列化
            MessagePack msgpack = new MessagePack();
            // Serialize
            byte[] bytes = msgpack.write(src);
    
            //利用MessagePack进行反序列化
            MyMessage2 dst = msgpack.read(bytes, MyMessage2.class);
            System.out.println("msgpack 原始数据:" + src);
            System.out.println("msgpack 反序列化:" + dst);
            
            
        }
    
    }

    执行结果:

    Exception in thread "main" org.msgpack.MessageTypeException: Expected raw value, but got boolean
        at org.msgpack.unpacker.Accept.acceptBoolean(Accept.java:33)
        at org.msgpack.unpacker.MessagePackUnpacker.readOneWithoutStackLarge(MessagePackUnpacker.java:154)
        at org.msgpack.unpacker.MessagePackUnpacker.readOneWithoutStack(MessagePackUnpacker.java:139)
        at org.msgpack.unpacker.MessagePackUnpacker.readOne(MessagePackUnpacker.java:73)
        at org.msgpack.unpacker.MessagePackUnpacker.readString(MessagePackUnpacker.java:502)
        at org.msgpack.template.StringTemplate.read(StringTemplate.java:46)
        at org.msgpack.template.StringTemplate.read(StringTemplate.java:25)
        at org.msgpack.template.AbstractTemplate.read(AbstractTemplate.java:31)
        at com.my.msgpack.SimpleMessagePackPractice$MyMessage2_$$_Template_1305193908_1.read(SimpleMessagePackPractice$MyMessage2_$$_Template_1305193908_1.java)
        at org.msgpack.template.AbstractTemplate.read(AbstractTemplate.java:31)
        at org.msgpack.MessagePack.read(MessagePack.java:388)
        at org.msgpack.MessagePack.read(MessagePack.java:371)
        at com.my.msgpack.SimpleMessagePackPractice.main(SimpleMessagePackPractice.java:61)

    参考:https://www.i4k.xyz/article/dly41721/101995555

    参考:https://github.com/msgpack/msgpack/blob/master/spec.md

  • 相关阅读:
    总体和样本
    素数和合数
    Scrum 体验活动笔记
    敏捷 扑克上的时间估算(转)
    Python爬取拉勾网职位
    无头浏览器Chromedriver、Phantomjs安装及教程、Chrome插件xpath下载及安装
    Python爬取智联招聘职位信息
    MATLAB 信号与系统
    Python爬虫学习(2)- Ajax的Get、Post方法实战
    Python爬虫学习(1)
  • 原文地址:https://www.cnblogs.com/vickylinj/p/15397631.html
Copyright © 2011-2022 走看看