将多态Json对象反序列化为POJO



我将Json Book请求定义为

{
"book" : {
"type" : "PRINT",
"value" : {
"weight" : "1lb"
}
}
}

{
"book" : {
"type" : "EBOOK",
"value" : {
"size" : "1MB"
}
}
}

Value是一个多态对象。

我将我的Java POJO定义如下。我将value定义为多态对象。

@Getter
@Builder
@JsonDeserialize(builder = BookRequest.BookRequestBuilder.class)
public class BookRequest
{
@NonNull
private Book book;
}

书籍被定义为

@Builder
@Getter
@JsonDeserialize(builder = Book.BookBuilder.class)
public class Book
{
@NonNull
private BookType type;
@NonNull
private BookValue value;
}

BookValue被定义为多态对象。

public interface BookValue 
{
}

PrintBook是类型

@Getter
@Builder
@JsonDeserialize(builder = PrintBook.PrintBookBuilder.class)
public class PrintBook implements BookValue
{
private String weight;
}

书籍类型定义为枚举

@Getter
public enum BookType
{
EBOOK,
PRINT
}

当我试图用下面的代码反序列化PRINT book 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;
}

但是,我得到这个错误

com.fasterxml.jackson.databind.exc.InvalidDefinitionException:无法构造jacksonannotations.books.BookValue的实例(不存在像默认构造函数一样的创建者(:抽象类型需要映射到具体类型,具有自定义反序列化程序,或包含其他类型信息在[来源:未知;行:-1,列:-1](通过参考链:jacksonannotations.books.BookRequest$BookRequestBuilder[quot;book"]->jacksonannotations.bbooks.book$BookBuilder["value"](

我已经研究过不能构造-Jackson的实例,但这并没有帮助。

有人能帮助我理解我是否正确地对上面例子中的Java pojo进行了建模吗?

谢谢,帕万

从错误消息中,您可以看到Jackson试图构造BookValue的实例。这会失败,因为BookValue是一个接口。

所以你需要告诉Jackson应该如何处理这种多态性。这个页面提供了一个很好的概述:https://www.baeldung.com/jackson-inheritance

您没有提供BookBuilder实现的详细信息。我假设它遵循一个常规的构建器模式,作为构造函数的替代方案。请注意,这并不能帮助Jackson确定要实例化哪个子类。

您可以使用unified-jdocs,这是我创建的一个库,用于在不使用任何POJO对象的情况下读取和写入JSON文档。对于您的问题,只需编写以下代码行即可:

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");

您可以使用类似的方式写入这些路径:

d.setString("$.book.value.weight", "1LB");
d.setString("$.book.value.size", "1MB");

这个库提供了许多其他功能,可以用来操作JSON文档。将文档结构锁定到模板的模型文档、字段级验证、比较、合并文档等功能。

显然,只有当您想在没有POJO对象的情况下工作时,您才会考虑它。或者,您可以使用它来使用自己的方法读取和写入POJO对象。

在上查看https://github.com/americanexpress/unify-jdocs.

最新更新