Reputation: 21310
I am building a rest API using Jersey
where XML and JSON
outputs are allowed depending on what format client prefers(using Accept
header).The service sends the below class as an output which looks like this
@XmlRootElement
public class ProjectDetails{
private List<Attachment> attachments;
private Map<String, List<Attachment>> imageCategory;
@XmlTransient
public List<Attachment> getAttachments() {
return attachments;
}
public void setAttachments(List<Attachment> attachments) {
this.attachments = attachments;
}
public Map<String, List<Attachment>> getImageCategory() {
if(attachments == null || attachments.size() == 0){
return null;
}
Map<String, List<Attachment>> map = new HashMap<String, List<Attachment>>();
for (Attachment img : attachments){
String key = img.getCategory();
if(BaseUtil.hasText(key)){
List<Attachment> values = map.get(key);
if (values == null){
values = new ArrayList<Attachment>();
}
values.add(img);
map.put(key, values);
}
}
this.imageCategory = map ;
return imageCategory;
}
public void setImageCategory(Map<String, List<Attachment>> imageCategory) {
this.imageCategory = imageCategory;
}
}
I don't want attachments field
as an output so marked it with @XmlTransient
rather I want to form a Map
using the attachments field and send it as an output.
In case of JSON
format, I am getting the correct response.But in case of XML
, I am not getting any output when I hit the service.
I think it is related to this Map field because if I remove Map field and add some other field like String then I get that field in response.
Please let me know how to resolve this.
Update:
After some googling, i found XmlAdapter
solution and implemented as below
public class MapAdapter extends
XmlAdapter<MapAdapter.AdaptedMap, Map<String, List<Attachment>>> {
public static class AdaptedEntry {
public String key;
public List<Attachment> value = new ArrayList<Attachment>();
}
public static class AdaptedMap {
List<AdaptedEntry> entries = new ArrayList<AdaptedEntry>();
}
@Override
public AdaptedMap marshal(Map<String, List<Attachment>> map)
throws Exception {
AdaptedMap adaptedMap = new AdaptedMap();
for (Entry<String, List<Attachment>> entry : map.entrySet()) {
AdaptedEntry adaptedEntry = new AdaptedEntry();
adaptedEntry.key = entry.getKey();
adaptedEntry.value = entry.getValue();
adaptedMap.entries.add(adaptedEntry);
}
return adaptedMap;
}
@Override
public Map<String, List<Attachment>> unmarshal(AdaptedMap adaptedMap)
throws Exception {
List<AdaptedEntry> adapatedEntries = adaptedMap.entries;
Map<String, List<Attachment>> map = new HashMap<String, List<Attachment>>(
adapatedEntries.size());
for (AdaptedEntry adaptedEntry : adapatedEntries) {
map.put(adaptedEntry.key, adaptedEntry.value);
}
return map;
}
And then
@XmlJavaTypeAdapter(MapAdapter.class)
public Map<String, String> getImageCategory() {
But still it's not working..Anything I missed?
Upvotes: 2
Views: 631
Reputation: 2052
I have used your ProjectDetails
class a little bit changes I've made, and it provides response for both XML and JSON. Can you try this?
@XmlRootElement
public class ProjectDetails {
private List<Attachment> attachments;
private Map<String, ArrayList<Attachment>> imageCategory;
@XmlTransient
public List<Attachment> getAttachments() {
return attachments;
}
public void setAttachments(List<Attachment> attachments) {
this.attachments = attachments;
}
@XmlJavaTypeAdapter(MapAdapter.class)
public Map<String, ArrayList<Attachment>> getImageCategory() {
if(attachments == null || attachments.size() == 0){
return null;
}
Map<String, ArrayList<Attachment>> map = new HashMap<String, ArrayList<Attachment>>();
for (Attachment img : attachments){
String key = img.getCategory();
if(!key.equals("")){
ArrayList<Attachment> values = map.get(key);
if (values == null){
values = new ArrayList<Attachment>();
}
values.add(img);
map.put(key, values);
}
}
this.imageCategory = map ;
return imageCategory;
}
public void setImageCategory(Map<String, ArrayList<Attachment>> imageCategory) {
this.imageCategory = imageCategory;
}
}
And the Adapter class you can use the following
public class MapAdapter extends XmlAdapter<MapElement[], Map<String, ArrayList<Attachment>>>{
public MapElement[] marshal(Map<String, ArrayList<Attachment>> arg0) throws Exception {
MapElement[] mapElements = new MapElement[arg0.size()];
int i = 0;
for (Map.Entry<String, ArrayList<Attachment>> entry : arg0.entrySet()){
mapElements[i++] = new MapElement(entry.getKey(), entry.getValue());
}
return mapElements;
}
public Map<String, ArrayList<Attachment>> unmarshal(MapElement[] arg0) throws Exception {
Map<String, ArrayList<Attachment>> r = new HashMap<String, ArrayList<Attachment>>();
for (MapElement mapelement : arg0)
r.put(mapelement.key, mapelement.value);
return r;
}
}
I've changed the MapElement also
public class MapElement {
@XmlElement
public String key;
@XmlElement
public ArrayList<Attachment> value;
private MapElement() {
}
public MapElement(String key, ArrayList<Attachment> value) {
this.key = key;
this.value = value;
}
}
And the Attachement class should have getter setter methods
public class Attachment {
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
private String category;
public Attachment(String cat){
this.category = cat;
}
}
Upvotes: 2