java - 使用 ObjectMapper 反序列化到参数化类时出现 ClassCastException,即使使用 TypeReference 和 TypeFactory
问题描述
尝试使用 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);
但我仍然得到同样的例外。
这些问题中没有涉及到我的场景中是否有一些特别之处?
我能想到的一件事是 myFoo
实际上是一个@AutoMatter
生成类的带注释的接口:
@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);
解决方案
当您Optional
在POJO
结构中使用时,您需要启用Jdk8Module
from jackson-modules-java8
。下面的示例显示,注册此模块后,我们可以序列化和反序列化数据:
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 - 如何从java更改jni中的char
- python - 递归返回错误的列表列表
- html - 如何在中心修复谷歌地图标记?
- django - django 模板中的 zip 和 formset
- c++ - 如何使用 C++03 约束且没有外部库执行基于正则表达式的字符串操作?
- uwp - 使用 JSON.NET 在 Win 10 Mobile 上序列化 Contacts.Contact 时出现奇怪的行为
- python - 3 点牛顿科茨公开规则
- electron - electron:如何在提交到苹果商店之前测试一个 MAS 包?
- c++ - 派生类调用使用非继承成员的继承函数
- ios - 在其他动态框架中使用动态框架的正确方法是什么?