当前位置: 首页 > 知识库问答 >
问题:

用Jackson序列化泛型接口子类

宋高谊
2023-03-14

我有一个带有几个实现类的通用接口,需要通过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会导致以下异常:

组织。科德豪斯。杰克逊。地图JsonMappingException:未找到类测试$Success的序列化程序,也未找到创建BeanSerializer的属性(为了避免异常,请禁用SerializationConfig.Feature.FAIL_ON_EMPTY_bean))

为什么Jackson希望我注册一个序列化程序——我认为完整数据绑定的意义在于我不需要这么做?

上述方法正确吗?

共有1个答案

空鸿云
2023-03-14

首先,您需要注册专用类型,以便使用工厂方法TypeFactory.construct专业类型与Jackson一起使用它。然后,专门化类型应该是一个bean(它应该有一个默认的构造函数、getters和setters)来反序列化它。

看看这些测试澄清剂。

@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;
    }
}
 类似资料:
  • 问题内容: 我正在尝试制作一个使用Jackson来反序列化POJO的类。 看起来像这样… 我对此实施有2个问题。 首先是我将类类型传递给方法,以便对象映射器知道应反序列化的类型。有使用泛型的更好方法吗? 同样在get方法中,我将一个从objectMapper返回的对象强制转换为T。这看起来特别讨厌,因为我必须在此处强制转换T,然后还必须从调用它的方法中强制转换对象类型。 我在该项目中使用了Robo

  • 我用Jackson编写了自己的序列化程序。它接受一个变量或类,并返回任何简单类型的值。 示例:serialize(new MyClass(2.0))将返回一个值为 2.0 的双精度值,其中 MyClass 如下所示: 因此,为了获得正确的值,我需要设置@JsonValue,但是,当我序列化一个没有@JsonValue注释的对象(例如UUID)时,它会返回预期的UUID字符串。 创建我自己的类没有@

  • 问题内容: 我有一个json字符串,应该将其反序列化为以下类 我该怎么做?这是通常的方式 但是我怎么提到T代表什么呢? 问题答案: 你需要为使用的每种通用类型创建一个对象,并将其用于反序列化。例如

  • 我有一个json字符串,我应该将其反序列化为以下类 我怎么做?这是通常的方式 但我怎么说T代表什么呢?

  • 我有以下控制器: 使用以下请求对象: 当帖子通过并查看我得到的对象时,有效负载列表中有LinkedHashMap对象,而不是我的DTO类型的对象。 如何让Spring jackson将JSON转换为我的DTO对象。请记住,我计划对其他对象列表重用包装器响应DTO,这就是我使用通用列表(List)的原因。 这是我正在尝试的JSON。