java - 使用 ObjectMapper 反序列化到参数化类时,甚至使用 TypeReference 和 TypeFactory 时出现 ClassCastException

标签 java generics jackson deserialization type-erasure

尝试使用 ObjectMapper 反序列化到参数化类时出现以下异常(对于非参数化类效果很好):

java.lang.ClassCastException: class java.util.LinkedHashMap cannot be cast to class com.xyz.A (java.util.LinkedHashMap is in module java.base of loader 'bootstrap'; com.xyz.A is in unnamed module of loader 'app')

原始代码如下:

Foo<A> request = OBJECT_MAPPER.readValue(payload, Foo.class);

我尝试过:

Foo<A> request = OBJECT_MAPPER.readValue(payload, new TypeReference<Foo<A>>() {});

以及:

JavaType myType = OBJECT_MAPPER.getTypeFactory()
    .constructParametricType(Foo.class, A.class);
Foo<A> request = OBJECT_MAPPER.readValue(payload, myType);

但我仍然遇到同样的异常。

我的场景是否存在这些问题未涵盖的特殊情况?

我能想到的一件事是我的Foo实际上是一个@AutoMatter - 生成类的带注释的接口(interface):

@AutoMatter
public interface Foo<T> {
  Optional<T> parent;
  Optional<List<T>> children;
}

通常情况下,映射到 AutoMatter 生成的类不会出现任何问题。它只是添加参数化 <T>这似乎引起了问题。

有人有想法吗?

<小时/>

编辑以回答 @MichalZiober 的问题:

在我的测试代码中,我实际上只是序列化我所知道的有效对象,然后反序列化它以取回我开始使用的对象:

Foo<A> myExampleObject;
ByteString.encodeUtf8(OBJECT_MAPPER.writeValueAsString(myExampleObject));
<小时/>

编辑2

好的,看来我们已经导入了该模块:

  @VisibleForTesting
  public static final ObjectMapper OBJECT_MAPPER = new ObjectMapper()
      .registerModule(new JodaModule())
      .registerModule(new GuavaModule())
      .registerModule(new AutoMatterModule())
      .registerModule(new Jdk8Module())
      .registerModule(new ProtobufModule())
      .setSerializationInclusion(JsonInclude.Include.NON_NULL)
      .configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
      .configure(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES, false)
      .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
      .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);

最佳答案

当您在POJO结构中使用Optional时,您需要从jackson-modules-java8启用Jdk8Module 。下面的示例显示,注册此模块后,我们可以序列化和反序列化数据:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import io.norberg.automatter.AutoMatter;
import io.norberg.automatter.jackson.AutoMatterModule;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;

public class JsonApp {

    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        mapper.enable(SerializationFeature.INDENT_OUTPUT);
        mapper.registerModule(new AutoMatterModule());
        mapper.registerModule(new Jdk8Module());

        String json = "{\"parent\":\"Aaaa\", \"children\":[\"a\"]}";
        System.out.println(mapper.readValue(json, Foo.class));


        Foo<StringWrapper> foo = new FooBuilder<StringWrapper>()
                .parent(new StringWrapperBuilder().value("PARENT").build())
                .children(Arrays.asList(new StringWrapperBuilder().value("CHILD1").build()))
                .build();
        json = mapper.writeValueAsString(foo);
        System.out.println(json);
        System.out.println(mapper.readValue(json, Foo.class));
    }
}
@AutoMatter
interface Foo<T> {
    Optional<T> parent();
    Optional<List<T>> children();
}

@AutoMatter
interface StringWrapper {
    String value();
}

上面的代码打印:

Foo{parent=Optional[Aaaa], children=Optional[[a]]}
{
  "parent" : {
    "value" : "PARENT"
  },
  "children" : [ {
    "value" : "CHILD1"
  } ]
}
Foo{parent=Optional[{value=PARENT}], children=Optional[[{value=CHILD1}]]}

关于java - 使用 ObjectMapper 反序列化到参数化类时,甚至使用 TypeReference 和 TypeFactory 时出现 ClassCastException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54875967/

相关文章:

java - 在 JPA Criteria Builder 中按 Oracle 函数排序

java - 如何运行简单的 Java 程序

java - Json 到 Java 对象的转换 - Jackson 失败

java - jackson 无法显示空数组 : null inside ([null] )

Java 将子类型实例添加到父类(super class)型的集合中?

java - Spring MVC MappingJackson2JsonView 集合元素重复

java - "Main Method not Public"- 尝试在 Eclipse 上运行程序时出现错误消息

java - 如何在 JUnit 中构建自动回复 JMS 监听器(在 OpenEJB 中)

java - 为什么 JavaFX TableView#setItems 采用 ObservableList<T> 而不是 ObservableList<?扩展 T>?

java - 自动将多个集合合并为一个