I have a class Food
which needs to be used as a deserialization class.
public class Food {
private VegetableConfiguration vegetableConfiguration;
private Color color;
// ...
// Getters/Setters
}
public interface VegetableConfiguration {
// ...
}
public class PotatoConfiguration implements VegetableConfiguration {
// ...
}
public class CarrotConfiguration implements VegetableConfiguration {
// ...
}
public class PepperConfiguration implements VegetableConfiguration {
// ...
}
public enum Color {
BROWN, ORANGE, RED
}
I need to select an implementation VegetableConfiguration
based on Color
I get from the response.
I'm trying to use JsonTypeInfo
form Jackson. According to JavaDoc it can be used on a property.
public class Food {
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
property = "color")
@JsonSubTypes({
@JsonSubTypes.Type(value = PotatoConfiguration.class, name = "BROWN"),
@JsonSubTypes.Type(value = CarrotConfiguration.class, name = "ORANGE"),
@JsonSubTypes.Type(value = PepperConfiguration.class, name = "RED"),
})
private VegetableConfiguration vegetableConfiguration;
private Color color;
// ...
// Getters/Setters
}
but it fails with the following error
org.springframework.web.client.RestClientException: Error while extracting response for type [Food] and content type [application/json;charset=UTF-8]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Missing type id when trying to resolve subtype of [simple type, class VegetableConfiguration]: missing type id property 'color' (for POJO property 'vegetableConfiguration'); nested exception is com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Missing type id when trying to resolve subtype of [simple type, class VegetableConfiguration]: missing type id property 'color' (for POJO property 'vegetableConfiguration')
How to make it select an implementation for VegetableConfiguration
on deserialization depending on color
?
Preferably without implementing a custom deserializer.
You need to use JsonTypeInfo.As.EXTERNAL_PROPERTY. From documentation:
Inclusion mechanism similar to
PROPERTY
, except that property is included one-level higher in hierarchy, i.e. as sibling property at same level as JSON Object to type. Note that this choice can only be used for properties, not for types (classes). Trying to use it for classes will result in inclusion strategy of basic PROPERTY instead.
See also: