I have a Cart object that contains a List<Product>, where Product is abstract and should be determined when deserializing the object, based upon the value of Cart.channel.
Cart:
public class Cart {
Channel channel; // Either Channel.ONLINE or Channel.PRINT
List<? extends Product>; // Either List of OnlineProduct or PrintProduct
}
I tried to write a custom Deserializer that simply uses a plain ObjectMapper to deserialize the nested property based upon the channel, but the Cart object has many more properties in reality and I don't want to extend the Deserializer every time I extend the Cart object.
Working with @JsonSubTypes as supposed in Deserializing json subtype based on parent property also didn't do the trick, since the property is a List instance:
public class Cart {
Channel channel; // Either Channel.ONLINE or Channel.PRINT
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "channel")
@JsonSubTypes(value = {
@JsonSubTypes.Type(value = SalesProductOnsite.class, name = "onsite"),
@JsonSubTypes.Type(value = SalesProductPrint.class, name = "print")
})
List<Product>; // Either List of OnlineProduct or PrintProduct
}
I also tried to ignore the field at runtime and then use the correct mapping, but to no avail:
public class CartDeserializer extends JsonDeserializer<Cart> {
private final ObjectMapper objectMapper = new ObjectMapper();
@Override
public Cart deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException {
Cart c = objectMapper.reader().withoutAttribute("products").readValue(jsonParser, Cart.class);
if(cart.channel == Channel.ONLINE) {
// cart.products = objectMapper.readValue(...)
} else {
// cart.products = objectMapper.readValue(...)
}
return cart;
}
}