Being Cynical
Being Cynical

Reputation: 61

Nested Mapping In Jackson

I am getting a JSON String as response as shown below

 {"size":3,"page-size":3,"subscribers-aircraft":
[
{"company-name":"ATCOMPANYTEST","tailno":"N345","status":"ACTIVE","network-status":"ACTIVE","id":18501,"contact":"SS Theairtime","model":"A-380-800","note":null,"created-at":"Jun 29, 2015 7:42:54 AM","packages":2,"username":"ATAIRCRAFTTEST","external-account":null,"consumer-type":"AIRCRAFT","isp-id":18493,"parent-id":18497,"subscriber-feature-id":13,"status-code":null,"status-msg":null},
{"company-name":"The AIRTIME 3","tailno":"VT456","status":"ACTIVE","network-status":"ACTIVE","id":18489,"contact":"Ramesh Anantarapu","model":"C-21","note":null,"created-at":"Jun 25, 2015 8:27:16 AM","packages":0,"username":"ramesh23","external-account":null,"consumer-type":"AIRCRAFT","isp-id":18469,"parent-id":18473,"subscriber-feature-id":9,"status-code":null,"status-msg":null},
{"company-name":"The AIRTIME 3","tailno":"VT23","status":"ACTIVE","network-status":"OFFLINE","id":18485,"contact":"Ramesh Anantarapu","model":"747-100","note":null,"created-at":"Jun 23, 2015 2:49:15 PM","packages":1,"username":"ramesh","external-account":null,"consumer-type":"AIRCRAFT","isp-id":18469,"parent-id":18473,"subscriber-feature-id":5,"status-code":null,"status-msg":null}],
"status-code":"AIRTIME-P4000","status-msg":"Successfully"}

This is a flat response.

I am now struggling to map it to a top level POJO called AircraftInfo which contains two other POJOs as its entities.

While for example : company-name, tailNo and status belongs directly to the AircraftInfo while user-name,id belongs to UserInfo POJO that is an entity in AircraftInfo.

Since the JSON response is flat, it is virtually turning out to be impossible to map such a response in a nested structure.

Can someone suggest the most elegant way to achieve?

Upvotes: 4

Views: 1178

Answers (2)

fps
fps

Reputation: 34470

One option is to make use of the @JsonCreator annotation:

public static class AircraftInfo {

    private final String companyName;

    private final String tailNo;

    private final UserInfo userInfo;

    @JsonCreator
    public AircraftInfo(Map<String, Object> flatProperties) {
        this.companyName = (String) flatProperties.get("company-name");
        this.tailNo = (String) flatProperties.get("tailno");
        UserInfo user = new UserInfo();
        user.setUserName((String) flatProperties.get("username"));
        user.setId((Integer) flatProperties.get("id"));
        this.userInfo = user;
    }

    // getters for final fields
}

UserInfo class would be as follows:

public class UserInfo {

    private String userName;

    private int id;

    // getters and setters
}

You could deserialize your JSON to the following Response POJO:

public class Response {

    private int size;

    @JsonProperty("page-size") // non standard JSON property name
    private int pageSize;

    @JsonProperty("subscribers-aircraft") // non standard JSON property name
    private List<AircraftInfo> subscribersAircraft; // use class defined above!

    @JsonProperty("status-code") // non standard JSON property name
    private String statusCode;

    @JsonProperty("status-msg") // non standard JSON property name
    private String statusMsg;

    // getters and setters
}

You could use these 2 classes as follows:

ObjectMapper mapper = new ObjectMapper();
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
mapper.setSerializationInclusion(Include.NON_NULL);
String json = // your exact json here, ESCAPED!
Response response = mapper.readValue(json, Response.class);

The response instance should be structured as per your requirements now, despite your JSON's flat structure.

Upvotes: 2

Sharon Ben Asher
Sharon Ben Asher

Reputation: 14383

You could write a custom Deserializer. However, Jackson's Streaming API isn't the most easy tool to work with.

So my advice to you: load the JSON into a HashMap (simply call ObjectMapper.readValue() with a Map.class second arg) and then you can construct your Objects and populate their state from the map

Upvotes: 1

Related Questions