Jackson将JSON对象字段反序列化为单个列表属性 [英] Jackson deserialize JSON object field into single list property

查看:198
本文介绍了Jackson将JSON对象字段反序列化为单个列表属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我只是想知道,给一个pojo:

I was just wondering, given a pojo:

public class MyProfileDto {
    private List<String> skills;
    //mutators; getSkills; setSkills + bunch of other fields
}

和技能字段的JSON:

and JSON for the skills field:

"skills":{
 "values":[
  {
     "id":14,
     "skill":{
      "name":"C++"
     }
  },
  {
     "id":15,
     "skill":{
      "name":"Java"
     }
  }
 ],
 "_total":2
}

是否可以使用Jackson将技能/值/技能/名称字段(即"Java","C ++")获取到目标Dto的字符串列表中,而无需为整个Dto创建自定义反序列化器?它具有许多字段,因此理想的解决方案将在可能的情况下为该字段包含一些自定义注释或反序列化器?

Is there any way using Jackson to get the skills/values/skill/name field (i.e. "Java", "C++") into the target Dto's String List without creating a custom deserializer for the entire Dto? It has many fields so an ideal solution would involve some custom annotation or deserializer for the one field if possible??

推荐答案

Jackson不包含任何XPath功能,但是您可以为每个属性定义转换器. Jackson将使用此转换器将输入类型转换为所需的输出类型.在您的示例中,输入类型为Map<String, Object>,输出类型为List<String>.可能这不是我们可以使用的最简单,最好的解决方案,但它允许我们仅为一个属性定义转换器,而无需为整个实体定义反序列化器.

Jackson does not contains any XPath feature but you can define converter for each property. This converter will be used by Jackson to convert input type to output type which you need. In your example input type is Map<String, Object> and output type is List<String>. Probably, this is not the simplest and the best solution which we can use but it allows us to define converter for only one property without defining deserializer for entire entity.

您的POJO课:

class MyProfileDto {

    @JsonDeserialize(converter = SkillConverter.class)
    private List<String> skills;

    public List<String> getSkills() {
        return skills;
    }

    public void setSkills(List<String> skills) {
        this.skills = skills;
    }
}

List<String> skills;属性的转换器:

class SkillConverter implements Converter<Map<String, Object>, List<String>> {

    @SuppressWarnings("unchecked")
    public List<String> convert(Map<String, Object> value) {
        Object values = value.get("values");
        if (values == null || !(values instanceof List)) {
            return Collections.emptyList();
        }

        List<String> result = new ArrayList<String>();
        for (Object item : (List<Object>) values) {
            Map<String, Object> mapItem = (Map<String, Object>) item;
            Map<String, Object> skillMap = (Map<String, Object>) mapItem.get("skill");
            if (skillMap == null) {
                continue;
            }

            result.add(skillMap.get("name").toString());
        }

        return result;
    }

    public JavaType getInputType(TypeFactory typeFactory) {
        return typeFactory.constructMapLikeType(Map.class, String.class, Object.class);
    }

    public JavaType getOutputType(TypeFactory typeFactory) {
        return typeFactory.constructCollectionLikeType(List.class, String.class);
    }
}

示例用法:

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.type.TypeFactory;
import com.fasterxml.jackson.databind.util.Converter;

public class JacksonProgram {

    public static void main(String[] args) throws IOException {
        ObjectMapper mapper = new ObjectMapper();

        MyProfileDto dto = mapper.readValue(new File("/x/json"), MyProfileDto.class);

        System.out.println(dto.getSkills());
    }
}

以上程序打印:

[C++, Java]

这篇关于Jackson将JSON对象字段反序列化为单个列表属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆