简体   繁体   中英

Deserialising complex nested Json using Jackson

I am struggling to deserialise complex nested Json data into Java objects I think my class structure is wrong. Here is my Json data:

    {
"resultsPerPage": 20,
"startIndex": 0,
"totalResults": 2,
"result": {
    "dataType": "CPE",
    "feedVersion": "1.0",
    "cpeCount": 2,
    "feedTimestamp": "2021-03-19T13:06",
    "cpes": [
        {
            "deprecated": false,
            "cpe23Uri": "cpe:2.3:o:microsoft:windows_10:1511:*:*:*:*:*:x64:*",
            "lastModifiedDate": "2015-12-09T17:28Z",
            "titles": [
                {
                    "title": "Microsoft Windows 10 1511 64-bit",
                    "lang": "en_US"
                }
            ],
            "refs": [
                {
                    "ref": "https://www.microsoft.com/en-us/",
                    "type": "Vendor"
                }
            ],
            "deprecatedBy": [],
            "vulnerabilities": [
                "CVE-2016-0174",
                "CVE-2016-0171"
            ]
        }

Here is the class I map the Json data to:

public class RESPONSE {

    Result result;
}

class Result {

    List<Cpes> cpes;
}

class Cpes {

    String cpe23Uri;
    List<Titles> titles;
    List<String> vulnerabilities;
}

class Titles{

    String title;
}

When I debug my code r in the below code is null and I think it's because my RESPONSE class isn't set up right.

        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

        RESPONSE r = mapper.readValue(response.getContent(), RESPONSE.class);

        System.out.println(r);

Your object model should match the structure of the JSON you are trying to read. For example, it'll have to look something like the following:

public class Response {
    private int resultsPerPage;
    private int startIndex;
    private int totalResults;
    private Result result;
    
    // Should include getters and setters
}

public class Result {
    private String dataType;
    private String feedVersion;
    private int cpeCount;
    private String feedTimestamp;
    private CPE[] cpes;

    // Should include getters and setters
}

public class CPE {
    private boolean deprecated;
    private String cpe23Uri;
    private String lastModifiedDate;
    private Title[] titles;
    private Ref[] refs;
    private String[] deprecatedBy;
    private String[] vulnerabilities;

    // Should include getters and setters
}

public class Title {
    private String title;
    private String lang;

    // Should include getters and setters
}

public class Ref {
    private String ref;
    private String type;

    // Should include getters and setters
}

Note that to keep the code sample short, I've omitted the getters and setters.

Edit: As Tugrul pointed out below, since fail on unknown property is disabled, it won't fail if there are missing fields in your model. The only issue is the missing getters and setters.

I also found another way to solve this issue for future reference.

I used a tree data structure to access my Json fields which means I can just declare a flat class:

public class Test {

    private String cpe23Uri;
    private String title;
    private List<String> vulnerabilities;


    public String getCpe23Uri() {
        return cpe23Uri;
    }

    public void setCpe23Uri(String cpe23Uri) {
        this.cpe23Uri = cpe23Uri;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public List<String> getVulnerabilities() {
        return vulnerabilities;
    }

    public void setVulnerabilities(List<String> vulnerabilities) {
        this.vulnerabilities = vulnerabilities;
    }
}

I then mapped using a Tree

        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

        JsonNode resultNode = mapper.readTree(response.getContent());

        Test t = new Test();

        t.setCpe23Uri(resultNode.get("result").get("cpes").get(0).get("cpe23Uri").textValue());

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