Tag Archives: Caused by: javassist.CannotCompileException: [source error] no such constructor: com.example..

MessagePack Error reported for deserialization of enumerated classes: Caused by: javassist.CannotCompileException: [source error] no such constructor: com.example..

Question 1:

Deserialized enumeration class:

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

}

An error occurs when messagepack deserializes the above enumeration class:

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

resolvent:

Change the annotation @ message to the annotation @ messagepackordinalenum( https://github.com/msgpack/msgpack/issues/66 )

Question 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)

This error is reported because the result of messagepack serialization contains only value, not key. Therefore, during deserialization, it is necessary to ensure that the order of attributes in the class must be completely consistent, otherwise an error will occur:

If the two attributes have the same type, they can be deserialized, but the values are disordered.

If the types of the two properties are inconsistent, a type mismatch exception will be thrown.

Therefore, the solution is to keep the order and type of serialized and deserialized objects consistent.

See below for details of messagepack:

1. What is a message pack

Let’s start with the official definition: messagepack is an efficient binary serialization format. It allows you to exchange data between multiple languages like JSON. But it’s faster and smaller.

From the official definition, the following conclusions can be drawn:

Messagepack is a binary serialization format, so its serialization results can exchange data among multiple languages.

In terms of performance, it is better than JSON’s serialization format.

In terms of result size, it is smaller than the serialization result of JSON.

However, the official did not mention the comparison between messagepack and Google Pb. In fact, Pb is better than messagepack in terms of space and time. However, Pb has less supported languages than messagepack and needs to write special software. Proto files are not convenient to use without messagepack.

2. Main concepts of messagepack

2.1 type system

The type system is the basis of message pack, and it is also the key that message pack occupies less space than JSON after serialization. The types currently included are as follows:

Integer represents an integer

Nil represents nil

Boolean   represents true or false

Float   represents an 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.

This type system maps the data formats we use in code development, and leaves room for users to expand freely through the type of extension. However, due to the limitation of representation, there are currently 127 extensions at most.

The scope that each type can represent can be viewed in the limitation section and extension types section of the message pack specification.

2.2 formats

In the message pack, the composition format of a value is as follows: type [length] [data]. Several examples are listed below. For a detailed and complete description, see the message pack specification in the appendix.

2.2.1 constant type

For example, the values of null, true, and false are fixedly mapped to the following values in the messagepack.

format name first byte (in binary) first byte (in hex)
nil eleven million 0xc0
false eleven million and ten 0xc2
true eleven million and eleven 0xc3

2.2.2 int type (including signed and unsigned integers)

Examples are as follows

0xCC indicates that the current value type is an unsigned integer and the length does not exceed 8 bits. The specific value content needs to be calculated through the content of the following 8 bits

0xcd indicates that the current value type is an unsigned integer and the length does not exceed 16 bits. The specific value content needs to be calculated through the content of the subsequent 16 bits

0xd0 indicates that the current value type is a signed integer and the length does not exceed 8 bits. The specific value content needs to be calculated through the content of the subsequent 8 bits

0xd1 indicates that the current value type is a signed integer and the length does not exceed 16 bits. The specific value content needs to be calculated through the content of the subsequent 16 bits

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 string

0xd9 indicates that the type of the current value is a string and the length does not exceed (2 ^ 8) – 1 bytes. The specific length needs to be calculated through the content of the subsequent 8 bits. The specific content of the string is the content represented by the bytes of the subsequent length

0xda indicates that the type of the current value is a string and the length does not exceed (2 ^ 16) – 1 bytes. The specific length needs to be calculated through the content of the subsequent 16 bit bits. The specific content of the string is the content represented by the bytes of the subsequent length

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 array

0xdc indicates that the type of the current value is array and the length does not exceed (2 ^ 16) – 1 elements, The specific length needs to be calculated through the contents of the following 16 bits (two bytes), and the calculated value is the number of array elements

0xdd indicates that the type of the current value is array and the length does not exceed (2 ^ 32) – 1 elements, The specific length needs to be calculated through the subsequent 32 bits (4 bytes), and the calculated value is the number of array elements

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

III. Why MessagePack uses fewer byte streams than json serialization
3.1 Visual Comparison
The first figure is the result of serializing the same data type with json and messagepack.

From the second figure, it is clear that messagepack takes up less space than json.

3.2 Serialization result is only value and the value is mapped exclusively


This image is from the official MessagePack website, used for comparison between json and MessagePack serialization results, is this really the case in practice?
I am using msgpack-0.6.12 version locally.
The code is as follows.

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 msgpack = new MessagePack();
        // Serialize
        byte[] bytes = msgpack.write(src);
        System.out.println("msgpack result length:"+bytes.length);
        

        String jsonResult = JSONObject.toJSON(src).toString();
        System.out.println("json result length:"+jsonResult.getBytes().length);
        
    }

}

The operation results are as follows:

json result length:27
msgpack result length:3

The result of JSON serialization is 27, which is the same as the result in the official website image. However, the serialization result of messagepack is 3, which is much smaller than the number in the official website.

According to the explanation of the picture above, it should be:

The first byte is 82, indicating that the serialized result has two elements

The second byte is C3, indicating that the value of the first element is true

The third byte is 00, indicating that the value of the second element is 0

To verify our conjecture, we can add a Boolean attribute to the mymessage class, but do not assign a value to this attribute. According to the Java specification, the value of this attribute is false. According to the messagepack specification, it will be converted to a byte C2, so that the length value of msgpack serialized is 4   The added value of JSON serialization needs to increase a lot, which is the length of attribute name + 5 (the length of false) + 4 (two double quotes, a comma and a colon need to be added). If the length of attribute name is 4, a total of 13 bytes will be added, and the total length is 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;
        

        String jsonResult = JSONObject.toJSON(src).toString();
        System.out.println("json result length:"+jsonResult.getBytes().length);
        

        MessagePack msgpack = new MessagePack();
        // Serialize
        byte[] bytes = msgpack.write(src);
        System.out.println("msgpack result length:"+bytes.length);
        
    }

}

The execution result of the above code also meets the guess:

json result length:40
msgpack result length:4

From this figure, messagepack is obviously better than JSON, especially when there are many attributes. Even if the key is removed from JSON, the serialized result takes up more space than the messagepack.

3.2 the attribute order of serialized objects cannot be changed

3.1 it is analyzed that the result of messagepack serialization only contains value, not key. Therefore, during deserialization, it is necessary to ensure that the order of attributes in the class must be completely consistent, otherwise an error will occur:

If the two attributes have the same type, they can be deserialized, but the values are disordered.

If the types of the two properties are inconsistent, a type mismatch exception will be thrown.

3.2.1 the order is different and the type is the same

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 msgpack = new MessagePack();
        // Serialize
        byte[] bytes = msgpack.write(src);

        MyMessage2 dst = msgpack.read(bytes, MyMessage2.class);
        System.out.println("msgpack Raw data:" + src);
        System.out.println("msgpack Deserialization:" + dst);
        
        
    }

}

The execution results of the above code are as follows:

msgpack Raw data:link:false;compact:true
msgpack Deserialization:link:true;compact:false

3.2.1 different sequences and types

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 msgpack = new MessagePack();
        // Serialize
        byte[] bytes = msgpack.write(src);


        MyMessage2 dst = msgpack.read(bytes, MyMessage2.class);
        System.out.println("msgpack Raw data:" + src);
        System.out.println("msgpack Deserialization:" + dst);
        
        
    }

}

Execution results:

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)