Deserializing json from retrofit using jackson whe

2019-02-25 03:53发布

问题:

The response from retrofit2 may be of the following types.(and we don't know before hand which response will come)

{
    "id": "abc",
    "place": "LA",
    "driverId": "abbabaaan"
}

or

{
    "id": "abc",
    "place": "LA",
    "driverId": {
        "name": "xyz",
        "id": "jygsdsah",
        "car": "merc"
    }
}

Is there any way to define a class so that while deserializing jackson will check the type of object "driverId" contains and assigns it to say "driverIdObj" field or "driverIdStr" field in the class.

回答1:

You could deserialize to a Map. Afterwards, you could inspect the map and decide to which of the 2 types you convert the map. Take a look at this answer: Deserializing JSON based on object type

To convert from Map to Object you can use ObjectMapper::convertValue, e.g

 mapper.convertValue(map, Response1.class)


回答2:

You can check whether the json has values inside it;

String jsonString= "{ ... }";
Object json = new JSONTokener(jsonString).nextValue();
 if (json instanceof JSONObject){ 
   //do operations related with object
 }
else if (json instanceof JSONArray) {
 //do operations based on an array
}


回答3:

Try this

JSONObject jsonObject = new JSONObject("your Response String");
Object obj = jsonObject.get("driverId");    //handle Exceptions
if (obj instanceof String){ 
   //do String stuff
}
else if (obj instanceof JSONObject) {
   //do json object stuff
}


回答4:

Make some special handling for the driverId field in your response class using the JsonNode class. Something like the following:

public class Response {
    private String id, place, driverIdStr;
    private DriverIdObj driverIdObj;

    // ... Various getters and setters omitted.

    public void setDriverId(JsonNode driverId) {
        if (driverId.isObject()) {
            // Process the complex version of DriverId.
            driverIdObj = new DriverIdObj( /* retrieve fields from JsonNode */ );
        } else {
            // Process the simple version of DriverId
            driverIdStr = driverId.asText();
        }
    }
}

This lets you maintain a normal approach for most of the response, while making it possible to handle the special field with a minimum of pain.