Я использую Jackson для десериализации ряда различных реализаций интерфейса Product
. Эти реализации продукта имеют разные поля, но у всех есть поле InsuredAmount
. Класс InsuredAmount
имеет поле значений и поле IAType
. IAType
является интерфейсом маркера с различными перечислениями в качестве реализаций.Как десериализовать на основе информации, доступной в родительском классе
Теперь вот в чем проблема: реализация enum интерфейса IAType
соответствует определенной реализации интерфейса Product
. Как я могу сделать общую реализацию и сказать Джексону, чтобы найти правильную реализацию вашего IAType? Должен ли я использовать общий параметр для продукта и интерфейса IAType, идентифицирующий реализацию продукта? Должен ли я использовать функциональный интерфейс Productable
для классов, идентифицирующих реализацию продукта? Как я могу сказать, что Джексон использовал эту реализацию?
Надеюсь, что приведенный ниже код поясняет проблему, я решил реализовать здесь интерфейс Productable
, но лучше использовать эту проблему для этой проблемы.
@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;
}
/* This should be on the product level, but if I can solve this problem,
the next level will just be more of the same.
*/
@JsonIgnore
@Override
public Product getProduct() {
return Product.PROD_A;
}
// Getters, setters, equals, etc. omitted.
}
-
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);
/* How to find out that the class calling the deserialization is InsuredAmountA, which
has getProduct() method that returns PROD_A, and matches the IATypeA that also returns
PROD_A, so I know to deserialize IATypeA, instead of other implementations of the IAType
interface?
*/
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));
}
}
Да, я уже изучил это. Не удалось выяснить, как это использовать в моем случае. –
@JsonTypeResolver, похоже, вам нужна аннотация, я бы посмотрел на источники (джексон - хороший кусок кода и легко понять) и беспокоит Тату Салоранту, который является автором - он обычно несет ответственность и живет где-то на западном побережье. –