I use Jackson to deserialize a number of different implementations of the Product interface. These product implementations have different fields, but everyone has an InsuredAmount field. This InsuredAmount class has a value field and an IAType field. IAType is a token interface with various enumerations as an implementation.
Now here's the problem: the enum implementation of the IAType interface corresponds to a specific implementation of the Product interface. How can I make a general implementation and tell Jackson to find the correct implementation of your IAType? Should I use a generic parameter for the product and the IAType interface that identifies the product implementation? Should I use the Productable functional interface for classes that identify the product implementation? How can I say that Jackson used this implementation?
I hope the code below explains the problem, I decided to implement the Productable interface here, but it would be better to also create a more efficient structure to solve this problem.
@JsonPropertyOrder({"type", "someInfo"}) public class InsuredAmount implements Productable, Serializable { private static final long serialVersionUID = 1L; private IAType type; private String someInfo; public InsuredAmount() { } public InsuredAmount(IAType typeA, String someInfo) { this.type = typeA; this.someInfo = someInfo; } @JsonIgnore @Override public Product getProduct() { return Product.PROD_A; }
-
public interface Productable { public Product getProduct(); }
-
public enum Product { PROD_A, PROD_B; }
-
@JsonDeserialize(using = IATypeDeserializer.class) public interface IAType extends Productable { }
-
public enum IATypeA implements IAType { FOO, BAR; @Override public Product getProduct() { return Product.PROD_A; } }
-
public class IATypeDeserializer extends StdDeserializer<IAType> { private static final long serialVersionUID = 1L; public IATypeDeserializer() { this(null); } public IATypeDeserializer(Class<?> vc) { super(vc); } @Override public IAType deserialize(JsonParser parser, DeserializationContext context) throws IOException, JsonProcessingException { JsonNode node = parser.getCodec().readTree(parser); return IATypeA.valueOf(node.asText()); } }
-
public class InsuredAmountTest { private final ObjectMapper mapper = new ObjectMapper(); @Test public void test01() throws IOException { InsuredAmount iaA = new InsuredAmount(IATypeA.FOO, "test it"); String json = mapper.writeValueAsString(iaA); assertThat(json, is("{\"type\":\"FOO\",\"someInfo\":\"test it\"}")); InsuredAmount iaA2 = mapper.readValue(json, InsuredAmount.class); IAType type = iaA2.getType(); assertThat(type, is(IATypeA.FOO)); assertThat(type.getProduct(), is(Product.PROD_A)); assertThat(iaA, is(iaA2)); } @Test public void test02() throws IOException { InsuredAmount iaA = new InsuredAmount(IATypeA.BAR, "test it"); String json = mapper.writeValueAsString(iaA); assertThat(json, is("{\"type\":\"BAR\",\"someInfo\":\"test it\"}")); InsuredAmount iaA2 = mapper.readValue(json, InsuredAmount.class); assertThat(iaA, is(iaA2)); } }