編集:最新の Jackson リリース候補を使用できる場合、問題は解決されます。ここで簡単なデモを組み立てましたhttps://github.com/MariusSchmidt/de.denktmit.stackoverflow/tree/main/de.denktmit.jackson
このスレッドhttps://github.com/FasterXML/jackson-databind/issues/1627を参照してください。問題について議論し、解決策を提案しています。私には有望に見えるマージがありますhttps://github.com/FasterXML/jackson-databind/pull/2813。したがって、@JsonTypeInfo(use = DEDUCTION) のパスをたどろうとするかもしれません。
ただし、ジャクソンの最新バージョンを使用できない場合は、次のようにします。
マージ リクエストをバックポートする、または
- Jackson を使用して、入力を一般的な JsonNode に逆シリアル化します
- https://github.com/json-path/JsonPathを使用して、1 つ以上のプロパティの存在を確認します。一部のコンテナ クラスは、クラス タイプを一意に識別するために必要なすべてのパスをラップできます。
- ここで説明されているように、JsonNode を決定されたクラスにマップしますJsonNode を POJO に変換します
このようにして、低レベルのマッピング ロジックを処理することなく、Jackson の機能を最大限に活用できます。
よろしくお願いします、
マリウス
動物
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.ObjectMapper;
import de.denktmit.stackoverflow.jackson.polymorphic.deductive.Bird;
import de.denktmit.stackoverflow.jackson.polymorphic.deductive.Fish;
import org.junit.jupiter.api.Test;
import java.util.List;
import static com.fasterxml.jackson.annotation.JsonTypeInfo.Id.DEDUCTION;
import static org.assertj.core.api.Assertions.assertThat;
@JsonTypeInfo(use = DEDUCTION)
@JsonSubTypes( {@JsonSubTypes.Type(Bird.class), @JsonSubTypes.Type(Fish.class)})
public class Animal {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
鳥
public class Bird extends de.denktmit.stackoverflow.jackson.polymorphic.deductive.Animal {
private double wingspan;
public double getWingspan() {
return wingspan;
}
public void setWingspan(double wingspan) {
this.wingspan = wingspan;
}
}
魚
public class Fish extends de.denktmit.stackoverflow.jackson.polymorphic.deductive.Animal {
private boolean freshwater;
public boolean isFreshwater() {
return freshwater;
}
public void setFreshwater(boolean freshwater) {
this.freshwater = freshwater;
}
}
ズーペン
public class ZooPen {
private String type;
private List<de.denktmit.stackoverflow.jackson.polymorphic.deductive.Animal> animals;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public List<de.denktmit.stackoverflow.jackson.polymorphic.deductive.Animal> getAnimals() {
return animals;
}
public void setAnimals(List<de.denktmit.stackoverflow.jackson.polymorphic.deductive.Animal> animals) {
this.animals = animals;
}
}
テスト
import com.fasterxml.jackson.databind.ObjectMapper;
import de.denktmit.stackoverflow.jackson.polymorphic.deductive.Animal;
import de.denktmit.stackoverflow.jackson.polymorphic.deductive.Bird;
import de.denktmit.stackoverflow.jackson.polymorphic.deductive.Fish;
import de.denktmit.stackoverflow.jackson.polymorphic.deductive.ZooPen;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
public class DeductivePolymorphicDeserializationTest {
private static final String birdString = "{\n" +
" \"name\": \"Tweety\",\n" +
" \"age\": 79,\n" +
" \"wingspan\": 2.9\n" +
" }";
private static final String fishString = "{\n" +
" \"name\": \"Nemo\",\n" +
" \"age\": 16,\n" +
" \"freshwater\": false\n" +
" }";
private static final String zooPenString = "{\n" +
" \"type\": \"aquaviary\",\n" +
" \"animals\": [\n" +
" {\n" +
" \"name\": \"Tweety\",\n" +
" \"age\": 79,\n" +
" \"wingspan\": 2.9\n" +
" },\n" +
" {\n" +
" \"name\": \"Nemo\",\n" +
" \"age\": 16,\n" +
" \"freshwater\": false\n" +
" }\n" +
" ]\n" +
"}";
private final ObjectMapper mapper = new ObjectMapper();
@Test
void deserializeBird() throws Exception {
de.denktmit.stackoverflow.jackson.polymorphic.deductive.Animal animal = mapper.readValue(birdString, de.denktmit.stackoverflow.jackson.polymorphic.deductive.Animal.class);
assertThat(animal).isInstanceOf(de.denktmit.stackoverflow.jackson.polymorphic.deductive.Bird.class);
}
@Test
void deserializeFish() throws Exception {
de.denktmit.stackoverflow.jackson.polymorphic.deductive.Animal animal = mapper.readValue(fishString, de.denktmit.stackoverflow.jackson.polymorphic.deductive.Animal.class);
assertThat(animal).isInstanceOf(de.denktmit.stackoverflow.jackson.polymorphic.deductive.Fish.class);
}
@Test
void deserialize() throws Exception {
de.denktmit.stackoverflow.jackson.polymorphic.deductive.ZooPen zooPen = mapper.readValue(zooPenString, de.denktmit.stackoverflow.jackson.polymorphic.deductive.ZooPen.class);
assertThat(zooPen).isInstanceOf(de.denktmit.stackoverflow.jackson.polymorphic.deductive.ZooPen.class);
}
}