【问题标题】:Jackson - deserialize into runtime specified classJackson - 反序列化为运行时指定的类
【发布时间】:2012-09-10 16:25:39
【问题描述】:

我正在编写一个使用 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);
    } // ...
  }
}

这是我用来测试的代码的 sn-p:

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)),但我遇到了同样的问题。

我很确定这与我将类型传递到序列化程序的方式有关,但到目前为止我还无法修复它。谢谢。

【问题讨论】:

标签: java json jackson


【解决方案1】:

目前还不清楚您到底想做什么:大部分代码都没有改变。 TypeReference 的具体用法是错误的:不能使用类型变量,类型必须是具体的。

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

【讨论】:

  • 这是 Couchbase Transcoder 的实现,这是一种在将数据放入缓存之前对其进行序列化/反序列化的方法。我正在使用 Jackson 将 JSON 序列化/反序列化为字符串,然后将其转换为 byte[] 并放入 CachedData 对象。我尝试将 Clazz.class 对象传递到 Serializer 并将调用更改为 objectMapper.readValue(cachedData.getData(), clazz);,但它仍然不起作用 - 我将更新问题。
  • 它现在工作了 - 我必须删除我之前添加的默认打字配置(在我发布问题之后)。谢谢!
【解决方案2】:

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

【讨论】:

  • 我无法注释类 - 我认为应该有另一种方式告诉“ObjectMapper”使用特定类进行反序列化?
【解决方案3】:

基于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>() {});

顺便说一句-“转码器”应该是“序列化器”?错字?

【讨论】:

  • 在合法使用时,这里不需要使用TypeReference。而应该直接通过Clazz.classTypeReference 仅在您需要为 Map&lt;String,Long&gt; 之类的东西指定泛型类型参数时才有用。
  • 我无法更改方法的签名,但是我可以为 Clazz 类传递 Class 对象。仍然无法正常工作,请查看其他评论。 (是的,序列化器和转码器是相当的,我在问问题的时候改变了代码,我忘了在所有地方都改变它!)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-05
  • 2017-11-06
  • 2014-01-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多