I’m trying to figure out response of a GET method API, it is returning extra attribute with name “attributesMap”
Reponse entity return code is return ResponseEntity.ok(document);
document model class
private String id; private String format; private List<Attribute> attributes; private String type; private String accessright; public Document() { } /** * Copy constructor. */ public Document(Document source) { this.id = source.id; this.format = source.format; this.type = source.type; this.accessright = source.accessright; this.attributes = source.attributes; } public static Document newDocument(String type, String id, String format, String accessright, List<Attribute> attributes) { Document document = new Document(); document.type = type; document.id = id; document.format = format; document.accessright = accessright; document.attributes = attributes; return document; } public static Document newCompleteDocument(String id, String type, String format, String accessright, List<Attribute> attributes) { Document document = new Document(); document.id = id; document.type = type; document.format = format; document.accessright = accessright; document.attributes = attributes; return document; } // // Getters and setters ahead public String getId() { return id; } public void setId(String id) { this.id = id; } public String getFormat() { return format; } public void setFormat(String format) { this.format = format; } public String getType() { return type; } public void setType(String type) { this.type = type; } public List<Attribute> getAttributes() { return attributes; } public void setAttributes(List<Attribute> attributes) { this.attributes = attributes; } public String getAccessright() { return accessright; } public void setAccessright(String accessright) { this.accessright = accessright; } public Map<String, List<String>> getAttributesMap() { Map<String, List<String>> attributesMap = getAttributes().stream().collect(Collectors.toMap(Attribute::getName, Attribute::getValues)); return attributesMap; } @Override public String toString() { final StringBuffer sb = new StringBuffer("Document{"); sb.append("id='").append(id).append('''); sb.append(", type='").append(type).append('''); sb.append(", format='").append(format).append('''); sb.append(", accessright='").append(accessright).append('''); sb.append(", attributes=[").append(attributes); if (attributes != null) { for (Attribute attribute:attributes) { sb.append(attribute.getName()).append(":").append(attribute.getValues().toArray()).append(","); } } sb.append("]}"); return sb.toString(); } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } Document document = (Document) o; if (id != null ? !id.equals(document.id) : document.id != null) { return false; } if (type != null ? !type.equals(document.type) : document.type != null) { return false; } if (format != null ? !format.equals(document.format) : document.format != null) { return false; } if (accessright != null ? !accessright.equals(document.accessright) : document.accessright != null) { return false; } return attributes != null ? attributes.equals(document.attributes) : document.attributes == null; } @Override public int hashCode() { int result = id != null ? id.hashCode() : 0; result = 31 * result + (type != null ? type.hashCode() : 0); result = 31 * result + (format != null ? format.hashCode() : 0); result = 31 * result + (accessright != null ? accessright.hashCode() : 0); result = 31 * result + (attributes != null ? attributes.hashCode() : 0); return result; } }
but the API reponse JSON as an extra attribute “attributesMap”. Sample JSON as below:
{ "id": "xxx", "format": "xx", "attributes": [ { "name": "attr1", "values": [ "val1" ] } ], "type": "test type", "accessright": "DELETE", "attributesMap": { "name": "attr1", "values": [ "val1" ] } }
Can anyone help me figure out how to check where this attribute coming from , when I debugged till the return return ResponseEntity.ok(document); there is no attributesMap in the document model object.
Advertisement
Answer
The problem in your case is that you have the getter getAttributesMap
. What will jackson serialize by default?
- All public fields
- All getter methods
What can you do?
- Rename the method
- Exclude the getter with
@JsonIgnore
@JsonIgnore public Map<String, List<String>> getAttributesMap() { Map<String, List<String>> attributesMap = getAttributes().stream().collect(Collectors.toMap(Attribute::getName, Attribute::getValues)); return attributesMap; }
You could also provide your own ObjectMapper bean with the following settings:
var mapper = new ObjectMapper(); mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); mapper.setVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.NONE);
or
var mapper = new ObjectMapper(); mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE); mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
This would only serialize fields, not getters.