【问题标题】:Deserializing a polymorphic Json object to a POJO将多态 Json 对象反序列化为 POJO
【发布时间】:2020-12-02 20:13:15
【问题描述】:

我将 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["book"]->jacksonannotations.books.Book$BookBuilder["value"])

我已经查看了Cannot construct instance of - Jackson,但这没有帮助。

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

谢谢, 帕万

【问题讨论】:

    标签: java json jackson polymorphism jackson-databind


    【解决方案1】:

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

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

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

    【讨论】:

      【解决方案2】:

      您可以使用 unify-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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-10-05
        • 2017-08-09
        • 1970-01-01
        • 1970-01-01
        • 2017-05-13
        • 1970-01-01
        • 2011-03-09
        • 1970-01-01
        相关资源
        最近更新 更多