【问题标题】:Jackson - Custom Deserializer doesn't read all the fields in JSONJackson - 自定义反序列化器不会读取 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://stackoverflow.com/a/9381832/12677470 一样配置 RestTemplateMappingJacksonHttpMessageConverter

【问题讨论】:

    标签: java json spring-boot jackson json-deserialization


    【解决方案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 类中删除它)
    • 最后我使用了没有反序列化器的正确 DTO。谢谢!
    猜你喜欢
    • 2021-06-17
    • 2018-11-17
    • 2016-02-12
    • 2011-04-12
    • 2016-01-29
    • 2013-01-18
    • 2018-03-06
    • 2014-08-02
    • 2013-10-10
    相关资源
    最近更新 更多