Jackson:将表示单字段 POJO 的 Map<String,Object> 的 JSON 转换为字段值的 Map<String,String>?

问题描述

我有一个类似于以下内容的复杂 JSON 对象:

{
    unneededobject1: {...},unneededobject2: {...},....,bigTargetobject: {
        "ABC": {
            targetField: "1234",unneededField1: "abcd",unneededField2: "abcd",...
        },"DEF": {
            targetField: "2345",...
    }
}

根包含许多对象,我需要挑出一个,它是一个内部对象列表(每个对象由一个唯一的字符串标识)。我的目标输出一个简单的 Map<String,String>,如下所示:

{
"ABC": "1234","DEF": "2345",...
}

我可以想到通过迭代对象和转换事物来做到这一点的方法,但我正在尝试使用 jackson 注释对象找到最干净的方法来做到这一点。我的目标是我可以像这样使用:

JsonNode entireGiantObject = callService(...);
MyObjectType temp = mapper.convertValue(entireGiantObject,MyObjectType.class);
Map<String,String> targetMap = temp.getTargetMap();

到目前为止,我通过创建一对类来隔离“bigTargetobject”和内部“targetField”,如下所示:

@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@ToString
@JsonIgnoreProperties(ignoreUnkNown = true)
public class MyObjectType {

    private Map<String,TargetField> targetMap;

    @JsonProperty("bigTargetobject")
    private void renameMap(Map<String,TargetField> bigTargetobject) {
        this.targetMap = bigTargetobject;
    }

}

@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@ToString
@JsonIgnoreProperties(ignoreUnkNown = true)
public class TargetField {

    private String targetField;

}

所以此时我的结果是 Map<String,TargetField> 类型。更进一步并自动生成 Map<String,String> 的最干净方法是什么?请注意,“TargetField”类的存在仅用于过滤原始 JSON 中的字段名称,否则它只是单个 String 的包装器。

解决方法

您可以使用 com.fasterxml.jackson.annotation.JsonAnySetter 注释。将类 MyObjectType 更改为:

@Data
@NoArgsConstructor
@AllArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
class MyObjectType {

    private Map<String,TargetField> targetMap = new HashMap<>();

    @JsonAnySetter
    private void renameMap(String key,TargetField targetField) {
        targetMap.put(key,targetField);
    }
}

你将能够像这样阅读它:

JsonNode bigO = entireGiantObject.get("bigTargetObject");
MyObjectType myObjectType = mapper.convertValue(bigO,MyObjectType.class);
System.out.println(myObjectType);

您也可以使用 JsonPath 库。