Why I'm not able to unwrap and serialize a Java map using the Jackson Java library?

JavaJsonJackson

Java 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;
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSuren RajuView Question on Stackoverflow
Solution 1 - JavaHari MenonView Answer on Stackoverflow
Solution 2 - JavaM. JustinView Answer on Stackoverflow