Considering a JSON like:
{"randomName1": {
"knownfield1": "a",
"knownfield2": [1,3,2,4]
},
"randomName2": {
"knownfield1": "0.20",
"knownfield2": [1,2,3,4]
}
}
public class PojoForJson {
HashMap<String, PojoType1> map = new HashMap<>();
@JsonAnyGetter
public HashMap<String , PojoType1> pojoType1Getter(){
return map;
}
@JsonAnySetter
public void pojoType1Setter(String key, PojoType1 value){
map.put(key,value);
}
}
If I have
PojoForJson pojo = new ObjectMapper().readValue(jsonInput,PojoForJson.class);
Then I try to write this back to the Json, I have to call and it works fine.
new ObjectMapper().writeValueAsString(pojo.getMap());
Now, this is a field in another POJO, let's call it PojoMain:
@Builder
public class PojoMain {
@Getter @Setter
private Type1 t1;
@Getter @Setter
private Type2 t2;
@Getter @Setter @JsonUnwrapped
private PojoForMap pojoForMap;
}
Expected result would be a JSON looking like
{
"t1":{...},
"t2":{...},
"randomName1":{...},
"randomName2":{...},
...............
}
Instead, it is
{
"t1":{...},
"t2":{...},
"pojoForMap":{
"map":{
"randomName1":{...},
...
}
}
}
If I change pojoForMap to HashMap<String, PojoType1>
@Builder
public class PojoMain {
@Getter @Setter
private Type1 t1;
@Getter @Setter
private Type2 t2;
@Getter @Setter @JsonUnwrapped
private HashMap<String, PojoType1> pojoForMap;
}
I still get:
{
"t1":{...},
"t2":{...},
"pojoForMap":{
"randomName1":{...},
........
}
}
}
My question is, how can I just serialize the map entries themselves in the main POJO, without any field names? I've used List in the past to forego this nuisance and ignore the actual list name, but this is a different case, where the field name is unknown.
I have tried using List<Map.Entry<String, PojoType1>>
, List<Pair<String, PojoType1>>
@JsonUnwrapped seems to not work on HashMaps
Why I'm not able to unwrap and serialize a Java map using the Jackson Java library?
Quoting relevant Answers here
@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
.
There is currently an an open issue at the Jackson project to allow support for @JsonUnwrapped
on Maps. It is not tagged as being in the upcoming 2.10 or 3.x versions of Jackson, so it does not look like it's on the near-term feature roadmap.
Until this feature is supported, the workaround about using @JsonAnySetter
/@JsonAnyGetter
appears to be the way to go.