A Deprecated @deprecated annotation was added to a member of DO, and the member was always null when deserialized from ProtoStuff. It took some time to locate this problem, for the record

Original ProtoStuff cannot deserialize Deprecated annotation member issue records

I. Full record

1. Environment

Protostuff was used as POJO serialization tool in the original project, and the corresponding version is

<dependency>
    <groupId>io.protostuff</groupId>
    <artifactId>protostuff-runtime</artifactId>
    <version>1.5.9</version>
</dependency>
<dependency>
    <groupId>io.protostuff</groupId>
    <artifactId>protostuff-core</artifactId>
    <version>1.5.9</version>
</dependency>
Copy the code

2. Scene repetition

After writing a simple demo, we added a member to the POJO with the deleted annotations and looked at the deserialization results

@Data
@NoArgsConstructor
@AllArgsConstructor
public static class BDO implements Serializable {
    private String a;
    @Deprecated
    private String b;
}

@Test
public void testSer(a) {
    BDO b = new BDO("10"."20");
    Schema<BDO> schema = RuntimeSchema.getSchema(BDO.class);

    LinkedBuffer buffer = LinkedBuffer.allocate(512);
    final byte[] protostuff;
    try {
        protostuff = ProtostuffIOUtil.toByteArray(b, schema, buffer);
    } finally {
        buffer.clear();
    }

    // deser
    BDO fooParsed = schema.newMessage();
    ProtostuffIOUtil.mergeFrom(protostuff, fooParsed, schema);
    System.out.println(fooParsed);
}
Copy the code

Here is the test output. You can see that in the deserialization result, b is null

The natural question is whether the member information is lost in serialization or skipped in deserialization.

We added a new POJO, similar to the BDO member, but without the @deprecated annotation

@Data
@NoArgsConstructor
@AllArgsConstructor
public static class NDO implements Serializable {
    private String a;
    private String b;
}
Copy the code

Then verify the result of BDO serialization, by deserializing to NDO object, if b member has a value, it indicates that the serialization is not lost;

@Test
public void testSer2(a) {
    BDO b = new BDO("10"."20");
    Schema<BDO> schema = RuntimeSchema.getSchema(BDO.class);

    LinkedBuffer buffer = LinkedBuffer.allocate(512);
    final byte[] protostuff;
    try {
        protostuff = ProtostuffIOUtil.toByteArray(b, schema, buffer);
    } finally {
        buffer.clear();
    }

    Schema<NDO> nSchema = RuntimeSchema.getSchema(NDO.class);
    NDO ndo = nSchema.newMessage();
    ProtostuffIOUtil.mergeFrom(protostuff, ndo, nSchema);
    System.out.println(ndo);
}
Copy the code

As you can see from the output below, deserialization does not come out and is discarded at serialization time

Then we will verify the result of NDO serialization. Since there are no Deprecated annotations, deserialization to NDO objects should be complete, so deserialization to BDO objects should be complete

@Test
public void testSer3(a) {
    NDO n = new NDO("10"."20");
    Schema<NDO> schema = RuntimeSchema.getSchema(NDO.class);

    LinkedBuffer buffer = LinkedBuffer.allocate(512);
    final byte[] protostuff;
    try {
        protostuff = ProtostuffIOUtil.toByteArray(n, schema, buffer);
    } finally {
        buffer.clear();
    }

    NDO ans = schema.newMessage();
    ProtostuffIOUtil.mergeFrom(protostuff, ans, schema);
    System.out.println(ans);

    Schema<BDO> bSchema = RuntimeSchema.getSchema(BDO.class);
    BDO bdo = bSchema.newMessage();
    ProtostuffIOUtil.mergeFrom(protostuff, bdo, bSchema);
    System.out.println(bdo);
}
Copy the code

As you can see from the output below, deserialization with a @deprecated annotation on the member also fails to get the correct result

3. Compatibility solution

Checking the documentation for Protostuf, I feel that the design concept is that with this deletion note, there is no need to continue to exist, so it is simply ignored. So I want this annotation to be serialized/deserialized, is there any way?

When I look at the API, I see that when I create the Schema, There is a way to IO. Protostuff. Runtime. RuntimeSchema# createFrom (Java. Lang. Class < T >, Java. Util. Map < Java. Lang. String, Java. Lang. String >, IO. Protostuff. Runtime. IdStrategy), you can specify a member list

So we have a creepy way of being compatible

@Test
public void testSer(a) {
    BDO b = new BDO("10"."20");
    Map<String, String> map = new HashMap<>();
    map.put("a"."a");
    map.put("b"."b");
    Schema<BDO> schema = RuntimeSchema.createFrom(BDO.class, map, RuntimeEnv.ID_STRATEGY);
    // Schema schema = RuntimeSchema.createFrom(BDO.class, new String[]{}, RuntimeEnv.ID_STRATEGY);

    LinkedBuffer buffer = LinkedBuffer.allocate(512);
    final byte[] protostuff;
    try {
        protostuff = ProtostuffIOUtil.toByteArray(b, schema, buffer);
    } finally {
        buffer.clear();
    }

    // deser
    BDO fooParsed = schema.newMessage();
    ProtostuffIOUtil.mergeFrom(protostuff, fooParsed, schema);
    System.out.println(fooParsed);
}
Copy the code

The test results are as follows: the deserialized instance has the corresponding data

4. Summary

With ProtoStuff, if a member has a Deprecated annotation on it, the member’s data will not be serialized or deserialized

II. The other

1. A gray Blog:liuyueyi.github.io/hexblog

A gray personal blog, recording all the study and work in the blog, welcome everyone to go to stroll

2. Statement

As far as the letter is not as good as, has been the content, purely one’s own words, because of the limited personal ability, it is hard to avoid omissions and mistakes, such as finding bugs or better suggestions, welcome criticism and correction, not grudging gratitude

  • Micro Blog address: Small Gray Blog
  • QQ: a gray /3302797840

3. Wechat official account:A gray blog