Jackson - 自定义反序列化器不会读取 JSON 中的所有字段

Posted

技术标签:

【中文标题】Jackson - 自定义反序列化器不会读取 JSON 中的所有字段【英文标题】:Jackson - Custom Deserializer doesn't read all the fields in JSON 【发布时间】:2020-04-30 13:07:09 【问题描述】:

我从 API 接收到这个 JSON:

    "link": [],
    "firstRecord": 1,
    "item": [
        
            "Customer": 
                "id": "1058207",
                "firstName": "foo",
                "lastName": "foo2",
                "nestedObj1": 
                    "id": "40008"
                ,
                "nestedObj2": 
                    "link": [],
                    "linkfoo": "lala",
                    "item": [
                             
                              "id": "266614",
                              "label": "NESTED_OBJ_2"
                            
                           ]
                  
              ]
           

我的反序列化函数

    @Override
    public CustomerView deserialize(JsonParser p, DeserializationContext ctxt)
            throws IOException, JsonProcessingException 

        //tried this too
        TreeNode treeNode = p.getCodec().readTree(p);

        // also this
        JsonNode node = p.getCodec().readTree(p);

        JsonNode simpleNode = new ObjectMapper().readTree(p);

        // use for each field that is not String
        ObjectMapper mapper = new ObjectMapper();

        Customer customer = new Customer();

        customer.setFirstName(simpleNode.get("Customer").get("firstName").textValue()); 

        NestedObj2[] arrayObj2 = mapper.readValue(
                        simpleNode.get("Customer").get("nestedObj2").get("item").toString(), 
                        NestedObj2[].class);

        customer.setArrayObj2(arrayObj2);

类 NestedObj2 具有 JSON 中的所有字段,“item”数组是作为字段的单独对象。

问题是,JsonNode 和 TreeNode 都没有看到字段“nestedObj2”,但其余字段在反序列化时都在其中 -> 在调试时检查。

我是否遗漏了配置中的某些内容,还是应该使用其他对象来反序列化?

谢谢!

编辑

最后,我按照@Mehrdad HosseinNejad 的建议使用了 DTO。 当我通过RestTemplate.exchange() 接收这个 JSON 时,我必须像这里 https://***.com/a/9381832/12677470 一样配置 RestTemplateMappingJacksonHttpMessageConverter

【问题讨论】:

【参考方案1】:

使用 DTO 类可能是一个更好的主意,无需创建自定义反序列化器

我编写了一个示例嵌套 DTO,如下所示

为客户创建 DTO 类

@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class Customer 

private Long id;
private String firstName;
private String lastName;
private NestedObj1 nestedObj1;
private NestedObj2 nestedObj2;

//getter and setter


为 NestedObj1 创建 DTO 类

@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class NestedObj1 

private Long id;

//getter and setter


为 NestedObj2 创建 DTO 类

@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class NestedObj2 

private List<String> link;
private String linkFoo;
private List<Item> item;

//getter and setter     


为 Item 创建 DTO 类

@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class Item 

private Long id;
private String label;

//getter and setter


创建这些 DTO 后,您可以简单地使用 ObjectMapper 类 将您的 JSON 转换为 Java 对象

Customer customer= new ObjectMapper().readValue(jsonFile, Customer.class);

有关忽略某些属性等更多选项,...您可以使用以下链接:

Jackson Annotation Examples

反序列化中的更多信息:

Getting Started with Deserialization in Jackson

【讨论】:

感谢您的回答!问题是,这个 json 有更多的字段,我不想放入我的 POJO,这就是我使用自定义反序列化器的原因。无论如何,我有你上面写的 DTO,但是反序列化器本身(JsonNode)在它的映射中没有字段'nestedObj2'。我正在寻找解决方案,发生了什么 如果您不想将任何 JSON 属性放入 POJO,您可以将 @JsonIgnore 放在该属性上以忽略它!。或者您可以从 POJO 中删除该属性(例如,如果您不想进行 id 转换,最好从 Item 类中删除它) ***.com/questions/38077728/… 最后我使用了没有反序列化器的正确 DTO。谢谢!

以上是关于Jackson - 自定义反序列化器不会读取 JSON 中的所有字段的主要内容,如果未能解决你的问题,请参考以下文章

使用 Jackson 自定义反序列化:扩展默认反序列化器

当值为“null”时,Jackson 忽略自定义字段反序列化器

Jackson 将 YAML 文件反序列化为 Map(没有自定义反序列化器)

如何让Jackson JSON生成的数据包含的中文以unicode方式编码

Spring Boot - 自定义 JsonDeserializer 被忽略

如何在自定义反序列化器 Spring Boot 中读取路径变量或 URL 参数