JSON文字列をJavaオブジェクトに変換したいのですが、このオブジェクトのクラスには抽象フィールドが含まれており、ジャクソンはインスタンス化できず、オブジェクトを生成しません。以下のような抽象クラスのデフォルト実装について伝えます
setDefault(AbstractAnimal.class, Cat.class);
または、JSON属性名に基づいて実装クラスを決定します。 JSONオブジェクトの場合:
{
...
cat: {...}
...
}
私はただ望んでいます:
setImpl("cat", Cat.class);
JacksonでJSONにクラス情報を埋め込むことは可能ですが、使用しているJSON形式を複雑にしたくありません。デフォルトの実装クラスを設定するだけで、または属性名(「cat」)で使用するクラスを決定したい-XStreamライブラリのように、次のように記述します。
xStream.alias("cat", Cat.class);
特に1行でそれを行う方法はありますか、それともさらにコードが必要ですか?
複数の方法があります。バージョン1.8より前では、おそらく最も簡単な方法があります。
@JsonDeserialize(as=Cat.class)
public abstract class AbstractAnimal { ... }
属性に基づいて決定する場合、@JsonTypeInfo
、自動書き込み(書き込み時)および型情報の使用を行います。
複数の種類の型情報(クラス名、論理型名)と包含メカニズム(as-included-property、as-wrapper-array、as-wrapper-object)があります。このページ: https://github.com/FasterXML/jackson-docs/wiki/JacksonPolymorphicDeserialization はいくつかの概念を説明しています。
非常に明確な例を含む本格的な答えは、ここにあります: https://stackoverflow.com/a/30386694/584947
ジャクソンはこれをポリモーフィックデシリアライゼーションと呼びます。
それは間違いなく私の問題を助けてくれました。データベースに保存している抽象クラスがあり、それをクラスの具体的なインスタンスに(理解できるように)非整列化する必要がありました。
親抽象クラスに適切に注釈を付ける方法と、アンマーシャリング時に実行時に使用可能なサブクラス候補の中から選択する方法をjacksonに教える方法を示します。
余分なフィールドを持つJSONも注釈付きのクラスも汚染しない場合は、必要なデフォルトのサブクラスを使用する非常に単純なモジュールとデシリアライザーを記述できます。定型的なコードのために複数行ですが、それでも比較的簡単です。
class AnimalDeserializer extends StdDeserializer<Animal> {
public AnimalDeserializer() {
super(Animal.class);
}
public Animal deserialize(JsonParser jsonParser, DeserializationContext context) throws IOException {
return jsonParser.readValueAs(Cat.class);
}
}
class AnimalModule extends SimpleModule {
{
addDeserializer(Animal.class, new AnimalDeserializer());
}
}
次に、このモジュールをObjectMapperに登録すると、それで終わりです(ZooはAnimalフィールドを持つコンテナクラスです)。
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new AnimalModule());
return objectMapper.readValue(json, Zoo.class);
この問題は、抽象クラスのアノテーション@JsonDeserializeで解決できます。JacksonExceptions Problems and Solutions https://www.baeldung.com/jackson-exception