首页 > 解决方案 > 将多态 Json 对象反序列化为 POJO

问题描述

我将 Json Book 请求定义为

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

或者

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

值是一个多态对象。

我将我的 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(没有创建者,如默认构造函数,存在):抽象类型需要映射到具体类型,具有自定义反序列化器,或者在 [Source : 未知; 行:-1,列:-1](通过参考链:jacksonannotations.books.BookRequest$BookRequestBuilder["book"]->jacksonannotations.books.Book$BookBuilder["value"])

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

有人可以帮助我理解我是否正确地对上面示例中的 Java pojo 进行建模?

谢谢,帕万

标签: javajsonjacksonpolymorphismjackson-databind

解决方案


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

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

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


推荐阅读