Jackson - 反序列化为运行时指定的类

时间:2012-09-10 16:25:39

标签: java json jackson

我正在编写一个使用Jackson序列化/反序列化对象的类。在编译时,我不知道我将序列化/反序列化的对象的类型。

我阅读了几篇关于TypeReferenceTypeFactory的用法的文章和问题,但我仍然遇到了一些问题。

我的课看起来像(删除了一些不相关的代码):

public class JsonSerializer<T> {

  private ObjectMapper objectMapper;
  private TypeReference typeReference;

  @PostConstruct
  public void init() {
      objectMapper = new ObjectMapper();
      typeReference = new TypeReference<T>(){ };
  }

  // ...


  public Object decode(CachedData cachedData) {
    try {
        return objectMapper.readValue(cachedData.getData(), typeReference);
    } // ...
  }
}

这是我用来测试的代码片段:

public class SerializerTest {

  private JsonSerializer<Clazz> serializer;
  private ObjectMapper objectMapper = new ObjectMapper();
  private static final String CHARSET = "UTF-8";
  private Clazz data = generateData(); // creates a simple object

  @BeforeMethod
  public void beforeMethod() {
      serializer = new JsonSerializer<Clazz>();
      serializer.init();
  }

  // ...

  public void shouldDecodeDataCorrectly() throws Exception {
    CachedData cachedData = new CachedData(0, 
      objectMapper.writeValueAsString(data).getBytes(CHARSET), 
      CachedData.MAX_SIZE);

    Object object = serializer.decode(cachedData);
    assertEquals(data, object);
  }

  public static class Clazz {
    // POJO with getters and setters
  }

}

据我所知,使用typeReference应该足以让我们知道反序列化器从字节流中读取的值应该放在Clazz对象中。但是,decode()方法返回的对象仍然是Map,我理解这是反序列化的默认类。

我还尝试更改decode()方法以返回return objectMapper.readValue(cachedData.getData(), objectMapper.getTypeFactory().constructType(typeReference)),但我遇到了同样的问题。

我很确定这是关于我将类型传递给序列化程序的方式,但到目前为止我还没能解决它。感谢。

3 个答案:

答案 0 :(得分:1)

目前尚不清楚你究竟想要做什么:大部分代码都没有做出改变。具体使用TypeReference是错误的:你不能使用类型变量,类型必须具体。

然而,也许解决方案比你想象的更简单。如果您可以跟踪原始Class,只需将其存储(或来自clazz.getName()的名称),并在反序列化时传递它。

答案 1 :(得分:0)

你检查过@JsonTypeInfo吗?请看一下它的文档。

答案 2 :(得分:0)

基于http://jackson.codehaus.org/1.9.9/javadoc/org/codehaus/jackson/type/TypeReference.html的javadoc 我将如何做到这一点:

从JsonSerializer

中删除typeReference字段

修改JsonSerializer.decode方法以将类型引用作为参数

将类型引用作为参数传递

Object object = transcoder.decode(cachedData, new TypeReference<Clazz>() {});

BTW - &#34;转码器&#34;应该是&#34;序列化器&#34;?错字?