Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Serialization of multiple nesting levels has issues #67

Closed
marsqing opened this issue Mar 23, 2017 · 4 comments
Closed

Serialization of multiple nesting levels has issues #67

marsqing opened this issue Mar 23, 2017 · 4 comments
Labels
Milestone

Comments

@marsqing
Copy link
Contributor

With latest snapshot version 2.9.0.pr3-SNAPSHOT, field of bigger tag will be serialized between fields of smaller tag. Below is the test case.
The serialization result is(in hex)
08 01 12 0a 12 02 08 03 08 02 12 02 08 04
While the correct result is(in hex)
08 01 12 0a 08 02 12 02 08 03 12 02 08 04

'08 02' is inserted between list element '12 02 08 03' and '12 02 08 04'

import static org.junit.Assert.assertEquals;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.protobuf.ProtobufMapper;
import com.fasterxml.jackson.dataformat.protobuf.schema.ProtobufSchema;
import com.fasterxml.jackson.dataformat.protobuf.schemagen.ProtobufSchemaGenerator;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.Arrays;
import java.util.List;
import org.junit.Test;

/**
 * Created by marsqing on 23/03/2017.
 */
public class BugReport {

  @Test
  public void test() throws Exception {
    ProtobufMapper mapper = new ProtobufMapper();
    ProtobufSchema schema = getSchema(mapper, Level1.class);

    System.out.println(schema.getSource());

    Level1 level1 = new Level1();
    Level2 level2 = new Level2();
    Level3 level3a = new Level3();
    Level3 level3b = new Level3();

    level1.setValue(1);
    level2.setValue(2);
    level3a.setValue(3);
    level3b.setValue(4);
    List<Level3> level3s = Arrays.asList(level3a, level3b);

    level1.setLevel2(level2);
    level2.setLevel3s(level3s);

    ByteArrayOutputStream bout = new ByteArrayOutputStream();
    mapper.writer(schema).writeValue(bout, level1);

    showBytes(bout.toByteArray());

    Level1 gotLevel1 = mapper.readerFor(Level1.class).with(schema).readValue(new ByteArrayInputStream(bout.toByteArray()));

//    byte[] correct = new byte[]{0x08, 0x01, 0x12, 0x0a, 0x08, 0x02, 0x12, 0x02, 0x08, 0x03, 0x12, 0x02, 0x08, 0x04};
//    Level1 gotLevel1 = mapper.readerFor(Level1.class).with(schema).readValue(new ByteArrayInputStream(correct));

    assertEquals(level1.getValue(), gotLevel1.getValue());
    assertEquals(level2.getValue(), gotLevel1.getLevel2().getValue());
    assertEquals(level3s.size(), gotLevel1.getLevel2().getLevel3s().size());
    assertEquals(level3a.getValue(), gotLevel1.getLevel2().getLevel3s().get(0).getValue());
    assertEquals(level3b.getValue(), gotLevel1.getLevel2().getLevel3s().get(1).getValue());
  }

  private ProtobufSchema getSchema(ObjectMapper mapper, Class<?> clazz) throws Exception {
    ProtobufSchemaGenerator gen = new ProtobufSchemaGenerator();
    mapper.acceptJsonFormatVisitor(clazz, gen);
    return gen.getGeneratedSchema();
  }

  private void showBytes(byte[] bytes) {
    for (byte b : bytes) {
      System.out.print(String.format("%8s", Integer.toHexString(b)).substring(6, 8).replaceAll(" ", "0") + " ");
    }
    System.out.println();
  }

  public static class Level1 {

    private int value;

    private Level2 level2;

    public int getValue() {
      return value;
    }

    public void setValue(int value) {
      this.value = value;
    }

    public Level2 getLevel2() {
      return level2;
    }

    public void setLevel2(Level2 level2) {
      this.level2 = level2;
    }
  }

  public static class Level2 {

    private int value;
    private List<Level3> level3s;

    public int getValue() {
      return value;
    }

    public void setValue(int value) {
      this.value = value;
    }

    public List<Level3> getLevel3s() {
      return level3s;
    }

    public void setLevel3s(List<Level3> level3s) {
      this.level3s = level3s;
    }
  }

  public static class Level3 {

    private int value;

    public int getValue() {
      return value;
    }

    public void setValue(int value) {
      this.value = value;
    }

  }

}
@marsqing
Copy link
Contributor Author

If leave out level3b, that is
List level3s = Arrays.asList(level3a);
then the result will be
0a 06 12 02 08 03 08 02
while the correct result is
0a 06 08 02 12 02 08 03

'08 02' 's ByteAccumulator mistakenly linked to '12 02' 's.

@cowtowncoder
Copy link
Member

Thank you for reporting this. And this fails with master or one of latest releases (2.8.7, 2.9.0.pr2)?

@marsqing
Copy link
Contributor Author

fail with master, I'll try the other two

@marsqing
Copy link
Contributor Author

Fail with all version, master(2.9.0.pr3-SNAPSHOT), 2.8.7 and 2.9.0.pr2.

cowtowncoder added a commit that referenced this issue Mar 27, 2017
@cowtowncoder cowtowncoder added this to the 2.8.8 milestone Apr 4, 2017
@cowtowncoder cowtowncoder changed the title Protobuf serialization message in List sequence error Protobuf serialization of multiple nesting levels has issues Apr 4, 2017
@cowtowncoder cowtowncoder changed the title Protobuf serialization of multiple nesting levels has issues Serialization of multiple nesting levels has issues Apr 4, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants