Jackson将JSON对象字段反序列化为单个列表属性

时间:2013-09-09 23:22:05

标签: java json jackson

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

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

和技能领域的JSON:

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

有没有办法使用Jackson将技能/值/技能/名称字段(即“Java”,“C ++”)放入目标Dto的字符串列表而不为整个Dto创建自定义反序列化器?它有很多字段,所以如果可能的话,理想的解决方案会涉及到一个字段的一些自定义注释或反序列化器吗?

1 个答案:

答案 0 :(得分:5)

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

您的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]