简体   繁体   中英

How to create Jackson XML POJO class for a JsonObject of JsonObjects

I'm trying to create POJOs for the following JSON structure. The Fields node is easy enough to wire up, but I'm unsure how to use annotations to wire up the Description node. If I had been defining the JSON structure for that node, I'd have create an JsonArray of JsonObjects, which would make the java class easy, but since I didn't, I need to figure out how to serialize the structure below:

{
    "Fields": {
        "Required": ["ftp.hostname"],
        "Optional": ["ftp.rootDirectory"]
    },
    "Description": {
        "ftp.hostname": {
            "label": "SFTP Hostname",
            "description": "SFTP server hostname or IP address"
        },
        "ftp.rootDirectory": {
            "label": "Root Directory",
            "description": "The root path on the Data Store accessible by this connector"
        }
    }
}

Note that the nodes in the Description object have names that correlate to the values defined in the Fields node, which means their node names can vary from payload to payload.

The class for the Fields node:

public class FieldDetails {

    public static final String REQUIRED = "Required";
    public static final String OPTIONAL = "Optional";

    @JsonProperty(value = REQUIRED, required = true)
    private List<String> required;

    @JsonProperty(value = OPTIONAL, required = true)
    private List<String> optional;
}

And what I have so far for the entire object:

public class FieldDefinitions {

    public static final String FIELDS = "Fields";
    public static final String DESCRIPTION = "Description";

    @JsonProperty(value = FIELDS, required = true)
    private FieldDetails fields;

    @JsonProperty(value = DESCRIPTION , required = true)
    private ??? descriptions;
}

That's the structure.

public class FieldDefinitions {
    @JsonProperty("Fields")
    public FieldDetails fields = new FieldDetails();

    @JsonProperty("Description")
    public Map<String, Property> properties = new HashMap<>();
}

public class FieldDetails {
    @JsonProperty("Required")
    public List<String> required = new ArrayList<>();

    @JsonProperty("Optional")
    public List<String> optional = new ArrayList<>();
}

public class Property {
    public String label;
    public String description;
}

Generally, you can always map any JSON object to Map<String, Object> . If JSON is complicated with many nested objects, Jackson will automatically pick correct type: Map for objects and List for arrays.

You can also declare class like below for Description properties.

class Description {
    private String label;
    private String description;
    // getters, setters, toString
}

The whole Description is a big JSON which you can map to Map<String, Description> . So, it could look like below:

class FieldDefinitions {

    public static final String FIELDS = "Fields";
    public static final String DESCRIPTION = "Description";

    @JsonProperty(value = FIELDS, required = true)
    private FieldDetails fields;

    @JsonProperty(value = DESCRIPTION, required = true)
    private Map<String, Description> descriptions;

    // getters, setters, toString
}

Rest is the same. Example app:

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.File;
import java.util.List;
import java.util.Map;

public class JsonApp {

    public static void main(String[] args) throws Exception {
        File json = new File("./resource/test.json").getAbsoluteFile();

        ObjectMapper mapper = new ObjectMapper();

        FieldDefinitions fields = mapper.readValue(json, FieldDefinitions.class);
        System.out.println("Required");
        fields.getFields().getRequired().forEach(r ->
                System.out.println(r + " = " + fields.getDescriptions().get(r)));
        System.out.println("Optional");
        fields.getFields().getOptional().forEach(r ->
                System.out.println(r + " = " + fields.getDescriptions().get(r)));
    }
}

For given JSON payload prints:

Required
ftp.hostname = Description{label='SFTP Hostname', description='SFTP server hostname or IP address'}
Optional
ftp.rootDirectory = Description{label='Root Directory', description='The root path on the Data Store accessible by this connector'}

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