web-dev-qa-db-ja.com

多相型を持つ1つのフィールド用のJacksonカスタムデシリアライザー

更新:

私はジャクソンのソースコードでデバッグして、メソッドでそれを見つけようとしました

deserialize(JsonParser jp, DeserializationContext ctxt)

SettableBeanProperty.Java

_valueTypeDeserializerがnullでない場合、_valueDeserializerは使用されません。

これは、TypeDeserializerがValueDeserializerより適切であるという正しい仮定ですか?


@JsonDeserializeを使用して、多相型を持つ1つのフィールドのカスタムデシリアライザーを定義しようとしています。 @JsonDeserialize@JsonTypeInfoを別々に使用できます。しかし、それらを一緒に使用すると、@JsonDeserialize注釈は無視されるようです。

クラス階層は次のとおりです。

1. Definition.Java

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type", defaultImpl = Definition.class)
@JsonSubTypes({@Type(value = Definition.class, name = "normal"),
    @Type(value = FormDefinition.class, name = "form")})
public class Definition {

    private String name;
    private String description;

    // getter&setter for name&description
}

2. FormDefinition.Java

public class FormDefinition extends Definition {

    private String formName;
    @JsonDeserialize(using = DefinitionDeserializer.class)
    private Definition definition;

    public String getFormName() {
        return formName;
    }

    public void setFormName(String formName) {
        this.formName = formName;
    }

    public void setDefinition(Definition definition) {
        this.definition = definition;
    }
}

3. DefinitionDeserializer.Java

public class DefinitionDeserializer extends JsonDeserializer<Definition> {

    @Override 
    public Definition deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
            throws IOException, JsonProcessingException {
        Definition definition = new Definition();
        String name = jsonParser.readValueAs(String.class);
        definition.setName(name);
        return definition;
    }
}

サンプルメイン

public class App 
{
    public static void main( String[] args ) throws IOException {
        String sampleData = "{\"type\":\"form\",\"definition\":\"super\",\"formName\":\"FormName\"}";
        ObjectMapper mapper = new ObjectMapper();
        Definition definition = mapper.readValue(sampleData, Definition.class);
        System.out.println(definition);
    }
}

サンプルのメインアプリを実行すると、例外がスローされます。

Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: Can not instantiate value of type [simple type, class jp.co.worksap.model.Definition] from String value ('super'); no single-String constructor/factory method (through reference chain: jp.co.worksap.model.FormDefinition["definition"])

これは、注釈付きデシリアライザAsPropertyTypeDeserializerの代わりにdefinitionクラスのFormDefinitionフィールドを逆シリアル化するためにDefinitionDeserializerを使用しているようです。

ここで注意が必要なのは、カスタムデシリアライザーを使用するフィールドも、@JsonTypeInfoを使用して多相性の問題を解決するDefinitionのタイプであると思います。

それらを一緒に使用する方法はありますか?ありがとう。

21
xi.lin

ジャクソンプロセス@JsonTypeInfo使用するデシリアライザーを選択する前。おそらく、デシリアライザーの選択は一般的にタイプに依存する可能性があるためです。ただし、カスタムデシリアライザーを指定するのと同じ方法で、フィールドに直接注釈を付けることで、フィールドごとに簡単に無効にすることができます。

@JsonDeserialize(using = DefinitionDeserializer.class)
@JsonTypeInfo(use = JsonTypeInfo.Id.NONE)
private Definition definition;
8
Anton Koscejev