简体   繁体   English

将多态 Json object 反序列化为 POJO

[英]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上查看。

将 json 反序列化为列表<object><div id="text_translate"><p>我有 json:</p><pre> "taxLevels": [{ "code": "VAT", "percentage": 19.0 } ]</pre><p> 这确实是List&lt;TTaxLevel&gt;</p><p> 我有<strong>Model.class</strong> :</p><pre> public class Model{ private final List&lt;TTaxLevel&gt; taxLevels; }</pre><p> 和<strong>TtaxLevel.class</strong> :</p><pre> @NoArgsConstructor public class TTaxLevel { private String code; private Double percentage; }</pre><p> 但我在这里收到错误:</p><blockquote><p> [Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize instance of java.util.LinkedHashMap&lt;java.lang.String,java.lang.String&gt; out of START_ARRAY token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of java.util.LinkedHashMap&lt;java.lang.String,java.lang.String&gt; out of START_ARRAY token at [Source: (PushbackInputStream); 行:36,列:19](通过参考链:...Model["taxLevels"])]]</p></blockquote><p> 我可以以某种方式强制jackson在这里ArrayList而不是Map吗? 这是一个问题。</p><p> 这是反序列化代码:</p><pre> Model model = new ObjectMapper().readValue(content, Model.class);</pre></div></object> - Deserializing json as List<Object>

暂无
暂无

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

相关问题 使用Jackson使用多态设置方法将JSON反序列化为对象 - Deserializing JSON into object with polymorphic setter methods using Jackson 使用@JsonTypeInfo和@JsonSubTypes将JSON反序列化为多态对象模型不起作用? - Deserializing JSON to polymorphic object model using @JsonTypeInfo & @JsonSubTypes not working? 使用 Jackson 为多态类反序列化 JSON - Deserializing JSON with Jackson for polymorphic classes 使用 Jooq 反序列化 pojo object 时出错 - Error in deserializing pojo object with Jooq 访问JSON多态POJO类 - Access JSON Polymorphic POJO Class 将 JSON 转换(反序列化)为 Java POJO Jackson - Convert (Deserializing) JSON to Java POJO Jackson 使用Gson抛出异常反序列化多态JSON - Deserializing polymorphic JSON with Gson throwing exception 使用Jackson进行不可变/多态POJO &lt; - &gt; JSON序列化 - Immutable/polymorphic POJO <-> JSON serialization with Jackson 反序列化JSON对象 - Deserializing JSON object 将 json 反序列化为列表<object><div id="text_translate"><p>我有 json:</p><pre> "taxLevels": [{ "code": "VAT", "percentage": 19.0 } ]</pre><p> 这确实是List&lt;TTaxLevel&gt;</p><p> 我有<strong>Model.class</strong> :</p><pre> public class Model{ private final List&lt;TTaxLevel&gt; taxLevels; }</pre><p> 和<strong>TtaxLevel.class</strong> :</p><pre> @NoArgsConstructor public class TTaxLevel { private String code; private Double percentage; }</pre><p> 但我在这里收到错误:</p><blockquote><p> [Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize instance of java.util.LinkedHashMap&lt;java.lang.String,java.lang.String&gt; out of START_ARRAY token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of java.util.LinkedHashMap&lt;java.lang.String,java.lang.String&gt; out of START_ARRAY token at [Source: (PushbackInputStream); 行:36,列:19](通过参考链:...Model["taxLevels"])]]</p></blockquote><p> 我可以以某种方式强制jackson在这里ArrayList而不是Map吗? 这是一个问题。</p><p> 这是反序列化代码:</p><pre> Model model = new ObjectMapper().readValue(content, Model.class);</pre></div></object> - Deserializing json as List<Object>
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM