简体   繁体   中英

Jackson: convert JSON representing a Map<String,Object> of single-field POJO's to a Map<String,String> of field values?

I have a complex JSON object similar to the following:

{
    unneededObject1: {...},
    unneededObject2: {...},
    ....,
    bigTargetObject: {
        "ABC": {
            targetField: "1234",
            unneededField1: "abcd",
            unneededField2: "abcd",
            ...
        },
        "DEF": {
            targetField: "2345",
            unneededField1: "abcd",
            unneededField2: "abcd",
            ...
        },
        ...
    }
}

The root contains many objects, and I need to pick out one, which is a list of inner objects (each identified by a unique string). My target output is a simple Map<String,String> like this:

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

I can think of ways to do this by iterating through to objects and converting things, but I'm trying to find the cleanest way to do this using jackson annotated objects. My goal is something I can use like this:

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

So far I have isolated "bigTargetObject" and internally "targetField" by creating a pair of classes as follows:

@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;

}

So at this point my result is of type Map<String,TargetField> . What is the cleanest way to go one step further, and automatically produce Map<String,String> ? Note that the "TargetField" class exists only for the purpose of filtering for the field name in the original JSON, and otherwise it's just a wrapper around a single String.

You can use com.fasterxml.jackson.annotation.JsonAnySetter annotation. Change class MyObjectType to:

@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);
    }
}

and you will be able to read it like this:

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

You can also use JsonPath library.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM