I have a json response which looks like below
{
"resourceType": "Topic",
"metadata": {
"lastUpdated": "2016-12-15T14:51:33.490-06:00"
},
"entry": [
{
"resource": {
"resourceType": "Outcome",
"issue": [
{
"response": "error",
"code": "exception"
},
{
"response": "success",
"code": "informational"
},
{
"response": "success",
"code": "informational"
}
]
}
},
{
"resource": {
"resourceType": "Data",
"id": "80",
"subject": {
"reference": "dataFor/80"
},
"created": "2016-06-23T04:29:00",
"status": "current"
}
},
{
"resource": {
"resourceType": "Data",
"id": "90",
"subject": {
"reference": "dataFor/90"
},
"created": "2016-06-23T04:29:00",
"status": "current"
}
}
]
}
Data and Outcome Class extends Resource.
I am using Spring RestTemplate.getForObject(url, someClass). I get below error
has thrown exception, unwinding now
org.apache.cxf.interceptor.Fault: Could not read JSON: Unrecognized field "response" (Class com.model.Resource), not marked as ignorable
at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@77a3e67a;
I understand that the json is not getting parsed to the child class of Resource. I want to do something like RestTemplate.getForObject(url, someClass) but this is not supported by java generics (wildcard). Please help
You'll want to use jackson to deserialize to a dynamic type, using resourceType as the field to indicate the actual type. Add these to your Resource class.
@JsonTypeInfo(property = "resourceType", use = Id.NAME)
@JsonSubTypes({ @Type(Data.class),
@Type(Outcome.class)
})
Here is a unit test that will prove out the behavior.
@Test
public void deserializeJsonFromResourceIntoData () throws IOException {
Data data = (Data) new ObjectMapper().readValue("{" +
" \"resourceType\": \"Data\"," +
" \"id\": \"80\"," +
" \"subject\": {" +
" \"reference\": \"dataFor/80\"" +
" }," +
" \"created\": \"2016-06-23T04:29:00\"," +
" \"status\": \"current\"" +
" }", Resource.class);
assertEquals(Integer.valueOf(80), data.getId());
assertEquals("dataFor/80", data.getSubject().getReference());
}
As for the cast, I've done it here just to demonstrate that it works, however, to be truly polymorphic, you probably want to have Resource contain all the behavior you need, and then everything is just a Resource.