There's a few topics like this, however I've read them all and still no luck.
I have a class to which I've made to deserialize some JSON
responses from a web service. In short, I've spent too much time looking at this and I'm hoping someone can pick out the error of my ways. As per title, I'm using the Jackson
libs.
Snippet of the class below:
final class ContentManagerResponse implements Serializable {
@JsonProperty("Results")
private List<OrgSearchResult> results = null;
@JsonProperty("PropertiesAndFields")
private PropertiesAndFields propertiesAndFields;
@JsonProperty("TotalResults")
private Integer totalResults;
@JsonProperty("CountStringEx")
private String countStringEx;
@JsonProperty("MinimumCount")
private Integer minimumCount;
@JsonProperty("Count")
private Integer count;
@JsonProperty("HasMoreItems")
private Boolean hasMoreItems;
@JsonProperty("SearchTitle")
private String searchTitle;
@JsonProperty("HitHighlightString")
private String hitHighlightString;
@JsonProperty("TrimType")
private String trimType;
@JsonProperty("ResponseStatus")
private ResponseStatus responseStatus;
@JsonIgnore
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
@JsonProperty("Results")
public List<OrgSearchResult> getResults() {
return results;
}
@JsonProperty("Results")
public void setResults(List<OrgSearchResult> results) {
this.results = results;
}
//additional getters and setters.
As said, Results
is the property which seems to be having the error.
The JSON response is below.
{
"Results": [
{
"TrimType": "Location",
"Uri": 1684
}
],
"PropertiesAndFields": {},
"TotalResults": 1,
"CountStringEx": "1 Location",
"MinimumCount": 1,
"Count": 0,
"HasMoreItems": false,
"SearchTitle": "Locations - type:Organization and id:24221",
"HitHighlightString": "",
"TrimType": "Location",
"ResponseStatus": {}
}
I'm using the same class to deserialize the following response and it works:
{
"Results": [
{
"LocationIsWithin": {
"Value": true
},
"LocationSortName": {
"Value": "GW_POS_3"
},
"LocationTypeOfLocation": {
"Value": "Position",
"StringValue": "Position"
},
"LocationUserType": {
"Value": "RecordsWorker",
"StringValue": "Records Co-ordinator"
},
"TrimType": "Location",
"Uri": 64092
}
],
"PropertiesAndFields": {},
"TotalResults": 1,
"MinimumCount": 0,
"Count": 0,
"HasMoreItems": false,
"TrimType": "Location",
"ResponseStatus": {}
}
Is the error message just misleading? The structure is identical aside from the second (working) payload not having some of the fields present in the class. I'd expect this one to error if anything.
For what its worth I've also included the OrgSearchResult
class below:
final class OrgSearchResult implements Serializable {
@JsonProperty("TrimType") private String trimType;
@JsonProperty("Uri") private String uri;
@JsonIgnore private Map<String, Object> additionalProperties = new HashMap<String, Object>();
//getters and setters
A lot of troubleshooting. I've even tried to use ignore properties can't seem to get them to work.
Full error:
org.codehaus.jackson.map.exc.UnrecognizedPropertyException: Unrecognized field "Results" (Class sailpoint.doet.contentmanager.ContentManagerResponse), not marked as ignorable at [Source: java.io.StringReader@5c6648b0; line: 1, column: 13] (through reference chain: sailpoint.doet.contentmanager.ContentManagerResponse["Results"])
You can improve readability of POJO
class by using PropertyNamingStrategy.UPPER_CAMEL_CASE strategy. Also, you can use JsonAnySetter
annotation to read all extra properties. Below example shows how model could look like:
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class JsonApp {
public static void main(String[] args) throws Exception {
File jsonFile = new File("./resource/test.json").getAbsoluteFile();
ObjectMapper mapper = new ObjectMapper();
mapper.setPropertyNamingStrategy(PropertyNamingStrategy.UPPER_CAMEL_CASE);
System.out.println(mapper.readValue(jsonFile, ContentManagerResponse.class));
}
}
class ContentManagerResponse {
private List<OrgSearchResult> results;
private Map<String, Object> propertiesAndFields;
private Integer totalResults;
private String countStringEx;
private Integer minimumCount;
private Integer count;
private Boolean hasMoreItems;
private String searchTitle;
private String hitHighlightString;
private String trimType;
private Map<String, Object> responseStatus;
// getters, setters, toString
}
class OrgSearchResult {
private String trimType;
private String uri;
private Map<String, Object> additionalProperties = new HashMap<>();
@JsonAnySetter
public void additionalProperties(String name, Object value) {
additionalProperties.put(name, value);
}
// getters, setters, toString
}
For first JSON
payload above code prints:
ContentManagerResponse{results=[OrgSearchResult{trimType='Location', uri='1684', additionalProperties={}}], propertiesAndFields={}, totalResults=1, countStringEx='1 Location', minimumCount=1, count=0, hasMoreItems=false, searchTitle='Locations - type:Organization and id:24221', hitHighlightString='', trimType='Location', responseStatus='{}'}
For second JSON
payload above code prints:
ContentManagerResponse{results=[OrgSearchResult{trimType='Location', uri='64092', additionalProperties={LocationSortName={Value=GW_POS_3}, LocationUserType={Value=RecordsWorker, StringValue=Records Co-ordinator}, LocationIsWithin={Value=true}, LocationTypeOfLocation={Value=Position, StringValue=Position}}}], propertiesAndFields={}, totalResults=1, countStringEx='null', minimumCount=0, count=0, hasMoreItems=false, searchTitle='null', hitHighlightString='null', trimType='Location', responseStatus='{}'}
You do not need to implement Serializable
interface.