3

我只是想知道,给定一个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 创建自定义反序列化器?它有很多字段,因此如果可能的话,理想的解决方案将涉及一个字段的一些自定义注释或反序列化器?

4

1 回答 1

6

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]
于 2013-09-10T11:09:20.523 回答