I have a JSON string which will be of the following format:
{
"response": {
"execution_status": "ready",
"report": {
"cache_hit": true,
"created_on": "2013-07-29 08:42:42",
"fact_cache_error": null,
"fact_cache_hit": true,
"header_info": null,
"name": null,
"report_size": "5871",
"row_count": "33",
"url": "report-download?id=278641c223bc4e4d63df9e83d8fcb4e6"
},
"status": "OK"
}
}
The response part of the JSON is common for a bunch of response types. The report part of this JSON holds good only for this response. So I had created a Response class as shown below with getters and setters (have not included the getters and setters here for brevity):
@JsonRootName(value = "response")
public class Response implements Serializable {
private static final long serialVersionUID = -2597493920293381637L;
@JsonProperty(value = "error")
private String error;
@JsonProperty(value = "error_code")
private String errorCode;
@JsonProperty(value = "error_id")
private String errorId;
@JsonProperty(value = "error_description")
private String errorDescription;
@JsonProperty(value = "method")
private String method;
@JsonProperty(value = "service")
private String service;
@JsonProperty(value = "status")
private String status;
@JsonProperty(value = "execution_status")
private String executionStatus;
}
And then, I created a Report class with the fields in the report element as below. The ReportResponse class will extend from the Response class (again the getters and setters are not included for brevity):
public class ReportResponse extends Response {
private static final long serialVersionUID = 4950819240030644407L;
@JsonProperty(value = "cache_hit")
private Boolean cacheHit;
@JsonProperty(value = "created_on")
private Timestamp createdOn;
@JsonProperty(value = "fact_cache_error")
private String factCacheError;
@JsonProperty(value = "fact_cache_hit")
private Boolean factCacheHit;
@JsonProperty(value = "header_info")
private String headerInfo;
@JsonProperty(value = "json_request")
private String jsonRequest;
@JsonProperty(value = "name")
private String name;
@JsonProperty(value = "report_size")
private Integer reportSize;
@JsonProperty(value = "row_count")
private Integer rowCount;
@JsonProperty(value = "url")
private String url;
}
Now when I use the ObjectMapper to map to the ReportResponse object, I get the following error:
String jsonString = "{\"response\": {\"execution_status\": \"ready\", \"report\": {\"cache_hit\": true, \"created_on\": \"2013-07-29 09:53:44\", \"fact_cache_error\": null, \"fact_cache_hit\": false, \"header_info\": null, \"name\": null, \"report_size\": \"5871\", \"row_count\": \"33\", \"url\": \"report-download?id=2ff62c07fc3653b68f2073e7c1aa0517\"}, \"status\": \"OK\"}}";
ObjectMapper mapper = new ObjectMapper();
ReportResponse reportResponse = mapper.readValue(jsonString, ReportResponse.class);
Caused by: com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "report"
I know that I can create a separate Report class and then embed it in the ReportResponse with the @JsonProperty anotation. Is there a way I can avoid that and mark the ReportResponse class with an annotation which would map it to the "report" element in the JSON?
There is no annotation which could handle this case yet. There is a ticket requesting this feature.
Here is a brief statement from one of the owners regarding this topic.
Quote from the mentioned statement:
Tatu Saloranta: "… @JsonProperty does not support transformations, since the data binding is based on incremental parsing and does not have access to full tree representation. Supporting @JsonUnwrapped was non-trivial, but doable; and thus converse ("@JsonWrapped") would be doable, theoretically speaking. Just plenty of work. …"