0

enableDefaultTyping とジェネリック TypeRefernce の両方を使用すると、逆シリアル化の問題が発生しました。Jackson は、どちらの型情報がより重要であるかを判断できないようです。このテスト ケースは、問題を示しています。

@Test
public void roundTripTest() throws JsonGenerationException,
        JsonMappingException, IOException {

    // 0 Value Test
    Integer[] integers = new Integer[] {};
    Wrap<Integer[]> beforeResult = new Wrap<Integer[]>(integers);

    File file = new File("/tmp/jsonTest");
    mapper.writeValue(file, beforeResult);

    TypeReference<Wrap<Integer[]>> typeRef = new TypeReference<JacksonMapperTest.Wrap<Integer[]>>() {
    };

    Wrap<Integer[]> afterResult = mapper.readValue(file, typeRef);

    assertNotNull(afterResult);

}


public static class Wrap<T> {

    private T wrapped;

    public Wrap() {
    }

    public Wrap(T wrapped) {
        this.wrapped = wrapped;
    }

    public T getWrapped() {
        return wrapped;
    }

    public void setWrapped(T wrapped) {
        this.wrapped = wrapped;
    }
}

マッパーは次のとおりです。

mapper = new ObjectMapper();
mapper.enableDefaultTyping();

例外は次のとおりです。

org.codehaus.jackson.map.JsonMappingException: No suitable constructor found for type [simple type, class JacksonMapperTest$Wrap<[Ljava.lang.Integer;>]: can not instantiate from JSON object (need to add/enable type information?)

かなり奇妙ですね。TypeRefernce の代わりに beforeResult.getClass を使用することで問題を回避できますが、それでも好ましい動作ではありません。

これを解決するために、何かオプションを見逃していませんか?

Jackson 1.9.3を使用していました

[編集]ラップされたオブジェクトとして配列の代わりにマップを使用すると、期待どおりに機能します!

4

2 に答える 2

2

これはジャクソンのバグのようです...しかし、その作者はおそらくそれがバグであるかどうかを判断する能力があります...ジャクソンから自由に変更できる場合は、genson http://code.googleを見てください.com/p/genson/ .

enableDefaultTyping に相当する Gensons は setUseRuntimeTypeForSerialization です (まったく同じではありませんが、ほとんどの場合非常に似ています)。シリアル化中にランタイム型を使用します。次に例を示します。

Genson genson = new Genson.Builder().setUseRuntimeTypeForSerialization(true).create();
String json = genson.serialize(beforeResult);
System.out.println(json);
GenericType<Wrap<Integer[]>> type = new GenericType<Wrap<Integer[]>>() {};
Wrap<Integer[]> afterResult = genson.deserialize(json, type);

EDIT genson を使用して多形または未知の型に逆シリアル化できるようにする必要がある場合は、Genson.Builder の setWithClassMetadata(true) を使用します。この機能は、実際には json オブジェクトに対してのみ使用されます (抽象クラスであるかどうかに関係なく)。

于 2012-10-24T22:19:39.350 に答える
0

正確な根本原因について 100% 確信があるわけではありませんが、これは Java の型の消去と、ジェネリックを認識した情報を渡し、それをデフォルトの型情報と混合することによる問題に関係していると思われます。型情報は、実際には非ジェネリック型のみに基づいています。ただし、特定の種類のジェネリック型 (マップ、コレクション) では機能します。

ただし、この場合、カスタム ジェネリック型があります。これが、ジャクソンが動的型付けの目的でプロパティのジェネリック型を示すことができない理由だと思います。

通常の回避策は、可能であればサブクラス化を試みることです。しかし幸いなことに、より良い回避策を見つけることができました。

于 2012-10-25T15:59:34.983 に答える