[英]Deserializing a polymorphic Json object to a POJO
I have Json Book requests defined as我有 Json 预订请求定义为
{
"book" : {
"type" : "PRINT",
"value" : {
"weight" : "1lb"
}
}
}
or或者
{
"book" : {
"type" : "EBOOK",
"value" : {
"size" : "1MB"
}
}
}
Value is a polymorphic object.值为多态 object。
I defined my Java POJOs as below.我将我的 Java POJO 定义如下。 I am defining value
as polymorphic object.我将value
定义为多态 object。
@Getter
@Builder
@JsonDeserialize(builder = BookRequest.BookRequestBuilder.class)
public class BookRequest
{
@NonNull
private Book book;
}
Book is defined as书被定义为
@Builder
@Getter
@JsonDeserialize(builder = Book.BookBuilder.class)
public class Book
{
@NonNull
private BookType type;
@NonNull
private BookValue value;
}
BookValue is defined as a polymorphic object. BookValue 定义为多态 object。
public interface BookValue
{
}
For which PrintBook is a type PrintBook 是一种类型
@Getter
@Builder
@JsonDeserialize(builder = PrintBook.PrintBookBuilder.class)
public class PrintBook implements BookValue
{
private String weight;
}
Book type is defines as an enum书籍类型定义为枚举
@Getter
public enum BookType
{
EBOOK,
PRINT
}
When I am trying to deserialize a PRINT book json with the below code当我尝试使用以下代码反序列化 PRINT 书 json
public deserializePrintBook{
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
try {
JsonNode node = createJsonNodeFromFile("src/jacksonannotations/resources/sampleBook.json");
BookRequest br = mapper.treeToValue(node, BookRequest.class);
System.out.println(br);
}
catch (Exception e ) {
e.printStackTrace();
}
}
public static JsonNode createJsonNodeFromFile(final String filePath) throws Exception
{
ObjectMapper objectMapper = new ObjectMapper();
File file = new File(filePath);
JsonNode testMessageEnvelope = objectMapper.readValue(
file,
JsonNode.class);
return testMessageEnvelope;
}
But, I am getting this error但是,我收到了这个错误
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of
jacksonannotations.books.BookValue
(no Creators, like default constructor, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information at [Source: UNKNOWN; com.fasterxml.jackson.databind.exc.InvalidDefinitionException:无法构造jacksonannotations.books.BookValue
的实例(没有创建者,如默认构造函数,存在):抽象类型需要映射到其他具体类型,或者包含自定义反序列化器在 [来源:未知; line: -1, column: -1] (through reference chain: jacksonannotations.books.BookRequest$BookRequestBuilder["book"]->jacksonannotations.books.Book$BookBuilder["value"])行:-1,列:-1](通过引用链:jacksonannotations.books.BookRequest$BookRequestBuilder["book"]->jacksonannotations.books.Book$BookBuilder["value"])
I already looked into Cannot construct instance of - Jackson , but that didn't help.我已经研究了无法构造 - Jackson 的实例,但这没有帮助。
Can someone help me understand if I am modeling the Java pojos in the above example correctly?有人可以帮助我理解我是否正确地在上面的示例中建模 Java pojos?
Thanks, Pavan谢谢,帕万
From the error message, you can see that Jackson tries to construct an instance of BookValue.从报错信息可以看出,Jackson试图构造一个BookValue的实例。 This fails, since BookValue is an interface.这失败了,因为 BookValue 是一个接口。
So you need to tell Jackson how this polymorphism is supposed to be handled.所以你需要告诉 Jackson 这个多态应该如何处理。 This page gives a nice overview: https://www.baeldung.com/jackson-inheritance此页面提供了一个很好的概述: https://www.baeldung.com/jackson-inheritance
You didn't provide details of your BookBuilder implementation.您没有提供 BookBuilder 实现的详细信息。 I assume it follows a regular builder pattern as an alternative to a constructor.我假设它遵循常规的构建器模式作为构造器的替代方案。 Note that this does not help Jackson to determine which subclass to instantiate.请注意,这无助于 Jackson 确定要实例化哪个子类。
You could use unify-jdocs, a library which I created to read and write JSON documents without using any POJO objects.您可以使用 unify-jdocs,这是我创建的一个库,用于在不使用任何 POJO 对象的情况下读取和写入 JSON 文档。 With respect to your problem, it would be as simple as writing the following lines of codes:关于您的问题,就像编写以下代码行一样简单:
Document d = new JDocument(s); // where s is a JSON string
String weight = d.getString("$.book.value.weight");
String size = d.getString("$.book.value.size");
You could use a similar way to write to these paths as so:您可以使用类似的方式写入这些路径,如下所示:
d.setString("$.book.value.weight", "1LB");
d.setString("$.book.value.size", "1MB");
This library offers a whole lot of other features which can be used to manipulate JSON documents.该库提供了许多其他功能,可用于操作 JSON 文档。 Features like model documents which lock the structure of documents to a template, field level validations, comparisons, merging documents etc. model 文档等功能将文档结构锁定到模板、字段级验证、比较、合并文档等。
Obviously, you would consider it only if you wanted to work without POJO objects.显然,只有当您想在没有 POJO 对象的情况下工作时才会考虑它。 Alternatively, you could use it to read and write a POJO object using your own method.或者,您可以使用自己的方法使用它来读取和写入 POJO object。
Check it out on https://github.com/americanexpress/unify-jdocs .在https://github.com/americanexpress/unify-jdocs上查看。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.