4

私はhttp://programmerbruce.blogspot.com/2011/05/deserialize-json-with-jackson-into.html )\ にあるものを適用しようとしており、それを私が取り組んできたことに適用しています。JSON 構造の「外部」要素と呼ぶものにはうまく機能しますが、ドキュメントがあまりないという苛立たしい問題に直面しています。

まず、私のコードは次のようなものです。

interface Parameters {
    // Couple random properties -- no problem here

    SubTypeParameters getSubTypeParameters(); // where SubTypeParameters are polymorphic
    void setSubTypeParameters(SubTypeParameters value);
}

@JsonSubTypes({
    @JsonSubTypes.Type(name = "a", value = ASubTypeParameters.class),
    @JsonSubTypes.Type(name = "b", value = BSubTypeParameters.class)
})
interface SubTypeParameters {
    String getValue();
    void setValue(String value);
}

@JsonTypeName(value = "a")
class ASubTypeParameters implements SubTypeParameters {
    // getter/setter implemented
}

@JsonTypeName(value = "b")
class BSubTypeParameters implements SubTypeParameters {
    // getter/setter implemented
}

私がやろうとしているのは、リンクされたブログ投稿に 6 番目のオプションを実装して、JSON が次のように表示されるようにすることです (「タイプ」要素が指定されていないことに注意してください。コンテキストに基づいています)。

{
    // other properties corresponding to the Parameters object
    "a": {
        "value": "value for a"
    }
}

また

{
    // other properties corresponding to the Parameters object
    "b": {
        "value": "value for b"
    }
}

私が避けようとしているのは、JSON オブジェクトに別の「型」変数を導入することです。むしろ、「a」または「b」の存在に基づいて ASubTypeParameters または BSubTypeParameters オブジェクトを構築する必要があることを知るために、上記の JSON の例のいずれかに提供されたコンテキストを使用することをお勧めします。

楽しいことに、Parameters クラス/オブジェクトもポリモーフィックであるため、次のような独自のカスタム デシリアライザー クラスを登録しました。

ObjectMapper mapper = new ObjectMapper();
StdDeserializer<Parameters> parameterDeserializer = new ParameterDeserializer();
SimpleModule module = new SimpleModule ( ... ); // simplifying this--no problem here
module.addDeserializer(Parameters.class, parameterDeserializer);
mapper.registerModule(module);
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

ただし、上記のデシリアライザーが上記の JSON の例のいずれかを逆シリアル化しようとすると、"a" または "b" を逆シリアル化しようとする部分に到達し、それらのプロパティを処理する方法がわからないことを示します (UnrecognizedPropretyException不明なプロパティ行での失敗を削除した場合)。私の質問は本当に次のようになります:何が欠けていますか (注釈など)?

私も追加しようとしました:

mapper.registerSubtypes(ASubTypeParameters.class, BSubTypeParameters.class)

としても

mapper.registerSubtypes(
    new NamedType(ASubTypeParameters.class, "a"),
    new NamedType(BSubTypeParameters.class, "b")
);

無駄に。

私はかなり近づいていることを知っており、ある種のカスタムサブタイプハンドラーを作成する必要があると推測していますが、私がやりたいことについてのドキュメントが不足しているようです (特に、ポリモーフィック型を逆シリアル化している場合) /ポリモーフィック要素も含むクラス)。

4

1 に答える 1

2

Jackson では、次の注釈を使用して、型情報を単一のフィールドの名前として保存するように構成できます@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.WRAPPER_OBJECT)。結果は JSON の例のようになります。

それを示すためにコードを少し変更しました:

public class JacksonPolymorphic2 {
    @JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.WRAPPER_OBJECT)
    @JsonSubTypes({
            @JsonSubTypes.Type(name = "a", value = ASubTypeParameters.class),
            @JsonSubTypes.Type(name = "b", value = BSubTypeParameters.class)
    })
    interface SubTypeParameters {
        String getValue();
        void setValue(String value);
    }

    @JsonTypeName(value = "a")
    static class ASubTypeParameters implements SubTypeParameters {
        ASubTypeParameters(String value) {
            this.value = value;
        }

        private String value;
        @Override
        public String getValue() {
            return value;
        }

        @Override
        public void setValue(String value) {
            this.value = value;
        }
    }

    @JsonTypeName(value = "b")
    static class BSubTypeParameters implements SubTypeParameters {
        BSubTypeParameters(String value) {
            this.value = value;
        }

        private String value;
        @Override
        public String getValue() {
            return value;
        }

        @Override
        public void setValue(String value) {
            this.value = value;
        }
    }

    public static void main(String[] args) throws JsonProcessingException {
        ASubTypeParameters a = new ASubTypeParameters("aType");
        BSubTypeParameters b = new BSubTypeParameters("bType");
        List<? super SubTypeParameters> list = new ArrayList<>();
        list.add(a);
        list.add(b);

        ObjectMapper mapper = new ObjectMapper();
        System.out.printf(mapper
                .writerWithType(new TypeReference<List<SubTypeParameters>>() {})
                .withDefaultPrettyPrinter()
                .writeValueAsString(list));
    }
}

出力:

[ {
  "a" : {
    "value" : "aType"
  }
}, {
  "b" : {
    "value" : "bType"
  }
} ]
于 2014-04-20T07:31:28.760 に答える