Why I'm not able to unwrap and serialize a Java map using the Jackson Java library?
JavaJsonJacksonJava Problem Overview
My bean looks like this:
class MyBean {
private @JsonUnwrapped HashMap<String, String> map = new HashMap<String, String>();
private String name;
public HashMap<String, String> getMap() {
return map;
}
public void setMap(HashMap<String, String> map) {
this.map = map;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
While I'm serializing the bean using the following code:
MyBean bean = new MyBean();
HashMap<String, String> map = new HashMap<String, String>();;
map.put("key1", "value1");
map.put("key2", "value2");
bean.setMap(map);
bean.setName("suren");
ObjectMapper mapper = new ObjectMapper();
System.out.println("\n"+mapper.writeValueAsString(bean));
I'm getting result like this:
{"map":{"key2":"value2","key1":"value1"},"name":"suren"}
but
{"key2":"value2","key1":"value1","name":"suren"}
is expected per the JacksonFeatureUnwrapping documentation. Why am I not getting the unwrapped result?
Java Solutions
Solution 1 - Java
@JsonUnwrapped
doesn't work for maps, only for proper POJOs with getters and setters. For maps, You should use @JsonAnyGetter
and @JsonAnySetter
(available in jackson version >= 1.6).
In your case, try this:
@JsonAnySetter
public void add(String key, String value) {
map.put(key, value);
}
@JsonAnyGetter
public Map<String,String> getMap() {
return map;
}
That way, you can also directly add properties to the map, like add('abc','xyz')
will add a new key abc
to the map with value xyz
.
Solution 2 - Java
There is an an open issue in the Jackson project to allow support for @JsonUnwrapped
on maps.
Until this feature is supported, the workaround about using @JsonAnySetter
/@JsonAnyGetter
proposed in another answer appears to be the way to go, and is in fact a suggested approach by the Jackson project author in the open issue:
> as per this: > > http://www.cowtowncoder.com/blog/archives/2011/07/entry_458.html > > one can use @JsonAnyGetter/setter to do something possibly similar. One missing pieces is that currently one must have getter (can't use it on Map filed), but that should be easy enough to address.
@JsonAnySetter
public void add(String key, String value) {
map.put(key, value);
}
@JsonAnyGetter
public Map<String,String> getMap() {
return map;
}