Reputation: 41271
A service I don't control is sending me JSON that looks like this when there is one item:
{ items: {
item: { ... }
}
... like this when there is no item:
{ items: null }
... and like this when there are two or more items:
{ items: {
item: [
{ ... },
{ ... }
]
}
}
I believe this is because the service was designed to produce XML like this:
<items>
<item>....</item>
<item>....</item>
</items>
... and has thrown the results at an XML->JSON convertor without paying much attention to the result.
Using Jackson, I can handle the "sometimes null, sometimes object, sometimes array" issue in Jackson by configuring my ObjectMapper with DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY
.
I can handle the two-layer structure by defining an Items
class with a field List<Item> item
.
However, the Items class is only there as a sop to the weird JSON format. Other than by writing a whole custom deserializer, can I persuade Jackson to deserialize to an object as if the structure was:
{ items: [ { ... }, { ... } ] }
?
Upvotes: 0
Views: 481
Reputation: 116630
Usually the easiest way to handle mapping is to reflect structure of data format in your POJO structure. So in this case, you would add one functionally unnecessary, but mapping-wise necessary, property:
public class POJO {
public ItemHolder items;
// might want convenience method for Java access, but not with getter name
public List<Item> items() {
return (items == null) ? null : items.item;
}
}
public class ItemHolder {
public List<Item> item;
}
and you do still also need to enable DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY
to handle mapping from single Item
into List<Item>
.
But perhaps the other answer of using @JsonUnwrapped
also helps; it is another option.
Upvotes: 0
Reputation: 38720
It looks like you have a root object which contains Items
property. In this case you can use @JsonUnwrapped
annotation. See below class:
class Root {
@JsonUnwrapped
private Items items = new Items();
public Items getItems() {
return items;
}
public void setItems(Items items) {
this.items = items;
}
}
Simple usage:
ObjectMapper mapper = new ObjectMapper();
Items items = new Items();
items.setItem(Arrays.asList(new Item(), new Item()));
Root wrapper = new Root();
wrapper.setItems(items);
String json = mapper.writeValueAsString(wrapper);
System.out.println(json);
Above program prints:
{"item":[{"name":"X"},{"name":"X"}]}
Upvotes: 1