Десериализация JSON при наличии нескольких реализаций интерфейса
Имеются две реализации dto наследуемые от одного интерфейса с одинаковыми названиями полей, но с разными @JsonProperty. В интерфейсе прописаны геттеры и сеттеры.
@Data
@ToString
@JsonIgnoreProperties(ignoreUnknown = true)
public class ResponseOldImpl implements Response {
@JsonProperty("phone")
private String phone;
@JsonProperty("name")
private String name;
}
@Data
@ToString
@JsonIgnoreProperties(ignoreUnknown = true)
public class ResponseActualImpl implements Response {
@JsonProperty("mobile_phone")
private String phone;
@JsonProperty("first_name")
private String name;
}
public interface Response {
public String getPhone();
public String getName();
public void setPhone(String Phone);
public void setName(String Name);
}
В тестах падает erxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of Response (no Creators, like default constructor, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information
Как в данном случае можно указать какую конкретно реализацию нужно десериализовать?
Ответы (1 шт):
Автор решения: Seryozha
→ Ссылка
Решение вышло таким:
public class ResponseDeserializer extends StdDeserializer<Response> {
protected ResponseDeserializer() {
super(Response.class);
}
@Override
public Response deserialize(JsonParser jp, DeserializationContext context)
throws IOException {
ObjectMapper mapper = new ObjectMapper();
JsonNode node = jp.getCodec().readTree(jp);
String text = node.toString();
if (text.contains("mobile_phone") || text.contains("first_name")) {
return mapper.readValue(text, ResponseActualImpl.class);
} else {
return mapper.readValue(text, ResponseOldImpl.class);
}
}
}
@Data
@ToString
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonDeserialize(as = ResponseOldImpl.class)
public class ResponseOldImpl implements Response {
@JsonProperty("phone")
private String phone;
@JsonProperty("name")
private String name;
}
@Data
@ToString
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonDeserialize(as = ResponseActualImpl.class)
public class ResponseActualImpl implements Response {
@JsonProperty("mobile_phone")
private String phone;
@JsonProperty("first_name")
private String name;
}
@JsonDeserialize(using = ResponseDeserializer.class)
public interface Response {
public String getPhone();
public String getName();
public void setPhone(String Phone);
public void setName(String Name);
}
Помогла эта статья. На имплементации нужно отдельно указать:
@JsonDeserialize(as = {имя имплементации}.class)