简体   繁体   English

如何使用Jackson-Databind顺序反序列化多个对象

[英]How to deserialize multiple objects sequentially using jackson-databind

I am using msgpack to serialize data. 我正在使用msgpack序列化数据。 I have some code works fine with serializing data. 我有一些代码可以很好地序列化数据。

public void testJackson() throws Exception {
    ByteArrayOutputStream out = new ByteArrayOutputStream();

    String data1 = "test data";
    int data2 = 10;
    List<String> data3 = new ArrayList<String>();
    data3.add("list data1");
    data3.add("list data1");

    ObjectMapper mapper = new ObjectMapper();
    mapper.writeValue(out, data1);
    mapper.writeValue(out, data2);
    mapper.writeValue(out, data3);

    // TODO: How to deserialize?

}

But now I don't know how to deserialize data. 但是现在我不知道如何反序列化数据。 I am not finding any solution anywhere. 我在任何地方都找不到任何解决方案。 It will be good if anyone can help how to proceed. 如果有人可以帮助您进行下去,那将是很好。

您将要使用ObjectMapperreadValue方法之一-可能是将Reader或InputStream作为第一个参数的方法。

The problem 问题

I have tried many of the readValue methods, but I only can get the first String, about the second and third value I have no idea 我已经尝试了许多readValue方法,但是我只能得到第一个String,而我不知道第二个和第三个值

The thing is, Jackson always reads the first data, since the data is neither deleted from the nor did you explicitly tell Jackson that the next data is from position A to position B 事实是,Jackson总是读取第一个数据,因为该数据既不会从中删除,也没有明确告诉Jackson,下一个数据是从位置A到位置B。

Solutions 解决方案

this example works and is similar to your code, but is not very elegant. 该示例可以正常工作,并且与您的代码相似,但不是很好。 Here I explicitly tell Jackson where my data is, but I have to know how it got written, which is a way too specific solution 在这里,我明确告诉杰克逊我的数据在哪里,但是我必须知道它是如何写入的,这是一种过于具体的解决方案

File dataFile = new File("jackson.txt");
if(!dataFile.exists())
  dataFile.createNewFile();
FileOutputStream fileOut = new FileOutputStream(dataFile);
ByteArrayOutputStream out = new ByteArrayOutputStream();
FileInputStream fileIn = new FileInputStream(dataFile);

String writeData1 = "test data";
int writeData2 = 10;
List<String> writeData3 = new ArrayList<String>();
writeData3.add("list data1");
writeData3.add("list data1");

ObjectMapper mapper = new ObjectMapper();
byte[] writeData1Bytes = mapper.writeValueAsBytes(writeData1);
out.write(writeData1Bytes);
byte[] writeData2Bytes = mapper.writeValueAsBytes(writeData2);
out.write(writeData2Bytes);
byte[] writeData3Bytes = mapper.writeValueAsBytes(writeData3);
out.write(writeData3Bytes);
out.writeTo(fileOut);

// TODO: How to deserialize?
int pos = 0;
byte[] readData = new byte[1000];
fileIn.read(readData);
String readData1 = mapper.readValue(readData, pos, writeData1Bytes.length, String.class);
pos += writeData1Bytes.length;
Integer readData2 = mapper.readValue(readData, pos, writeData2Bytes.length, Integer.class);
pos += writeData2Bytes.length;
ArrayList readData3 = mapper.readValue(readData, pos, writeData3Bytes.length, ArrayList.class);
pos += writeData3Bytes.length;

System.out.printf("readData1 = %s%n", readData1);
System.out.printf("readData2 = %s%n", readData2);
System.out.printf("readData3 = %s%n", readData3);

the file looks then like this 该文件看起来像这样

"test data"10["list data1","list data1"]

How to do it correctly 如何正确做

a way more elegant way is to encapsulate your data in an object which can be turned into a valid JSON string and from that Jackson won't need any more information 一种更优雅的方式是将数据封装在一个对象中,该对象可以转换为有效的JSON字符串,并且Jackson不需要任何更多信息

public class JacksonTest {
  public static class DataNode {
    @JsonProperty("data1")
    private String data1;
    @JsonProperty("data2")
    private int data2;
    @JsonProperty("data3")
    private List<String> data3;

    //needed for Jackson
    public DataNode() {
    }

    public DataNode(String data1, int data2, List<String> data3) {
      this.data1 = data1;
      this.data2 = data2;
      this.data3 = data3;
    }
  }

  public static void main(String[] args) throws Exception {
    File dataFile = new File("jackson.txt");
    if(!dataFile.exists())
      dataFile.createNewFile();
    FileOutputStream fileOut = new FileOutputStream(dataFile);
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    FileInputStream fileIn = new FileInputStream(dataFile);

    String writeData1 = "test data";
    int writeData2 = 10;
    List<String> writeData3 = new ArrayList<String>();
    writeData3.add("list data1");
    writeData3.add("list data1");

    DataNode writeData = new DataNode(writeData1, writeData2, writeData3);

    ObjectMapper mapper = new ObjectMapper();
    mapper.writeValue(out, writeData);
    out.writeTo(fileOut);

    // TODO: How to deserialize?
    DataNode readData = mapper.readValue(fileIn, DataNode.class);

    System.out.printf("readData1 = %s%n", readData.data1);
    System.out.printf("readData2 = %s%n", readData.data2);
    System.out.printf("readData3 = %s%n", readData.data3);
  }
}

the content of the file looks like this 文件的内容如下所示

{"data1":"test data","data2":10,"data3":["list data1","list data1"]}

@Japu_D_Cret Thank you for such a detailed answer! @Japu_D_Cret感谢您提供如此详细的答案! Actually I want to use msgpack to transfer data, and I made it work by using msgpack, here is my code 实际上我想使用msgpack传输数据,并且通过使用msgpack使它工作,这是我的代码

    ByteArrayOutputStream out = new ByteArrayOutputStream();

    String data1 = "test data";
    int data2 = 10;
    List<String> data3 = new ArrayList<String>();
    data3.add("list data1");
    data3.add("list data1");

    MessagePack packer = new MessagePack();

    packer.write(out, data1);
    packer.write(out, data2);
    packer.write(out, data3);

    // TODO: How to deserialize?

    BufferUnpacker unpacker = packer.createBufferUnpacker(out.toByteArray());
    System.out.println(unpacker.readString());
    System.out.println(unpacker.readInt());
    System.out.println(unpacker.read(Templates.tList(Templates.TString)));

Then I found jackson-databind on msgpack website and it supports msgpack format also. 然后我在msgpack网站上找到了jackson-databind,它也支持msgpack格式。 I do some tests on these two and found that jackson's serialize performance is better than msgpack, so I want to use jackson instead of msgpack. 我对这两个进行了一些测试,发现杰克逊的序列化性能优于msgpack,因此我想使用杰克逊代替msgpack。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM