3

Json を介してシリアル化および逆シリアル化する必要があるいくつかの実装クラスを持つ汎用インターフェイスがあります。完全なデータバインディングを使用して、Jackson を使い始めようとしていますが、あまり運がありません。

サンプル コードは、問題を示しています。

import org.codehaus.jackson.map.*;
import org.codehaus.jackson.map.type.TypeFactory;
import org.codehaus.jackson.type.JavaType;

public class Test {

    interface Result<T> {}

    static class Success<T> implements Result<T> {
        T value;
        T getValue() {return value;}
        Success(T value) {this.value = value;}
    }

    public static void main(String[] args) {
        Result<String> result = new Success<String>("test");
        JavaType type = TypeFactory.defaultInstance().constructParametricType(Result.class, String.class);
        ObjectMapper mapper = new ObjectMapper().enableDefaultTyping();
        ObjectWriter writer = mapper.writerWithType(type);
        ObjectReader reader = mapper.reader(type);

        try {
            String json = writer.writeValueAsString(result);
            Result<String> result2 = reader.readValue(json);
            Success<String> success = (Success<String>)result2;
        } catch (Throwable ex) {
            System.out.print(ex);
        }
    }
}

への呼び出しwriteValueAsStringにより、次の例外が発生します。

org.codehaus.jackson.map.JsonMappingException: クラス Test$Success のシリアライザーが見つからず、BeanSerializer を作成するためのプロパティが見つかりません (例外を回避するには、SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS を無効にします)

ジャクソンがシリアライザーを登録することを期待しているのはなぜですか?完全なデータバインディングのポイントは、これを行う必要がないということでしたか?

上記のアプローチは正しいですか?

4

1 に答える 1

3

まず、ファクトリメソッドを使用してJacksonで使用するには、特殊なタイプを登録する必要がありますTypeFactory.constructSpecializedType。次に、特殊な型は、それを逆シリアル化するためのBean(デフォルトのコンストラクター、ゲッター、およびセッターを持つ必要があります)である必要があります。

これらのテストクラリファイアを見てください。

@Test
public void canSerializeParametricInterface() throws IOException {
    final ObjectMapper mapper = new ObjectMapper().enableDefaultTyping();
    final JavaType baseInterface = TypeFactory.defaultInstance().constructParametricType(Result.class, String.class);
    final JavaType subType = TypeFactory.defaultInstance().constructSpecializedType(baseInterface, Success.class);
    final ObjectWriter writer = mapper.writerWithType(subType);
    final String json = writer.writeValueAsString(Success.create("test"));
    Assert.assertEquals("{\"value\":\"test\"}", json);
}

@Test
public void canDeserializeParametricInterface() throws IOException {
    final ObjectMapper mapper = new ObjectMapper().enableDefaultTyping();
    final JavaType baseInterface = TypeFactory.defaultInstance().constructParametricType(Result.class, String.class);
    final JavaType subType = TypeFactory.defaultInstance().constructSpecializedType(baseInterface, Success.class);
    final ObjectReader reader = mapper.reader(subType);
    final Success<String> success = reader.readValue("{\"value\":\"test\"}");
    Assert.assertEquals("test", success.getValue());
}

public static interface Result<T> {
}

public static class Success<T> implements Result<T> {

    private T value;

    public static <T> Success<T> create(T value) {
        final Success<T> success = new Success<T>();
        success.value = value;
        return success;
    }

    public T getValue() {
        return value;
    }

    public void setValue(T value) {
        this.value = value;
    }
}
于 2013-02-08T12:14:26.680 に答える