- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想我在这里遗漏了一些明显的东西,但我似乎无法使用 Spring/Kotlin/Jackson 反序列化一个简单的通用容器。
有问题的数据类型非常简单:
@JsonDeserialize(using = PatchableDeserializer::class)
sealed class Patchable<T> {
class Undefined<T>: Patchable<T>()
class Null<T>: Patchable<T>()
data class Present<T>(val content: T): Patchable<T>()
// …
}
反序列化器扩展了 ReferenceTypeDeserializer
,就像 jdk8 模块的 OptionalDeserializer
一样。
class PatchableDeserializer(javaType: JavaType, vi: ValueInstantiator, typeDeser: TypeDeserializer, deser: JsonDeserializer<*> ):
ReferenceTypeDeserializer<Patchable<*>>(javaType, vi, typeDeser, deser) {
// …
}
我假设 Jackson 会在这里填写 PatchableDeserializer
的构造函数参数。然而,情况似乎并非如此:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'my.namespace.PatchableDeserializer': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.fasterxml.jackson.databind.JavaType' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
我假设 Jackson 提供了 javaType
的值,因为我无法在编译时知道它。
这是我用来测试的代码,它会生成上述异常:
@RunWith(SpringRunner::class)
@JsonTest
class PatchableTest {
@Autowired
lateinit var objectMapper: ObjectMapper
@Test
fun patchableDeserialisesStringValue() {
val value: Patchable<String> = objectMapper.readValue("\"null\"", object: TypeReference<Patchable<String>>() {})
assertTrue(value.isPresent())
assertEquals("null", value.unsafeGetValue())
}
}
我错过了什么?此外,我真的很难在网上查找有关如何反序列化泛型类型的一些信息,因此,如果有人指出如何为泛型类型编写自定义反序列化程序,我将不胜感激。
最佳答案
通用容器的反序列化(那些扩展 com.fasterxml.jackson.databind.deser.std.ReferenceTypeDeserializer
)不能以这种方式注册。
您需要使用重写的 findReferenceDeserializer
方法注册 com.fasterxml.jackson.databind.deser.Deserializers
的自定义实现。调用此方法为引用类型的值定位反序列化器。
您还需要添加 com.fasterxml.jackson.databind.type.TypeModifier
将您的“通用容器”类型修改为 com.fasterxml.jackson.databind .type.ReferenceType
,因此您的自定义 ReferenceTypeDeserializer
将被调用。
最简单的方法是注册一个自定义 com.fasterxml.jackson.databind.Module
,它将addDeserializers
和addTypeModifier
。这种模块的一个很好的例子是 Jdk8Module
它为 java.util.Optional
及其 friend 完成所有工作。
MyRef
:MyRefDeserializer
完成主要工作。这只是一个例子。覆盖方法的确切实现(以及需要覆盖哪些方法)将取决于您的要求。
public final class MyRefDeserializer extends ReferenceTypeDeserializer<MyRef<?>> {
public MyRefDeserializer(JavaType fullType, ValueInstantiator vi,
TypeDeserializer typeDeser, JsonDeserializer<?> deser) {
super(fullType, vi, typeDeser, deser);
}
@Override
protected MyRefDeserializer withResolved(TypeDeserializer typeDeser, JsonDeserializer<?> valueDeser) {
return new MyRefDeserializer(_fullType, _valueInstantiator, typeDeser, valueDeser);
}
@Override
public MyRef<?> getNullValue(DeserializationContext ctxt) throws JsonMappingException {
return MyRef.of(_valueDeserializer.getNullValue(ctxt));
}
@Override
public Object getAbsentValue(DeserializationContext ctxt) throws JsonMappingException {
return MyRef.absent();
}
@Override
public MyRef<?> referenceValue(Object contents) {
return MyRef.of(contents);
}
@Override
public Object getReferenced(MyRef<?> reference) {
return reference.orElse(null);
}
@Override
public NullableOptional<?> updateReference(MyRef<?> reference, Object contents) {
return referenceValue(contents);
}
}
Deserializers
接口(interface)的实现:
public class MyRefDeserializers extends Deserializers.Base {
@Override
public JsonDeserializer<?> findReferenceDeserializer(ReferenceType refType, DeserializationConfig config,
BeanDescription beanDesc, TypeDeserializer contentTypeDeserializer, JsonDeserializer<?> contentDeserializer)
throws JsonMappingException {
if (refType.hasRawClass(MyRef.class)) {
return new MyRefDeserializer(refType, null, contentTypeDeserializer, contentDeserializer);
}
return null;
}
}
TypeModifier
的实现允许 Jackson 理解 MyRef
是一个 ReferenceType
类型:
public class MyRefTypeModifier extends TypeModifier {
@Override
public JavaType modifyType(JavaType type, Type jdkType, TypeBindings context, TypeFactory typeFactory) {
if (type.isReferenceType() || type.isContainerType()) {
return type;
}
if (type.getRawClass() == MyRef.class) {
return ReferenceType.upgradeFrom(type, type.containedTypeOrUnknown(0));
} else {
return type;
}
}
}
最后,Module
将注册反序列化器和类型修饰符:
public class MyRefModule extends Module {
@Override
public String getModuleName() {
return "MyRefModule";
}
@Override
public Version version() {
return Version.unknownVersion();
}
@Override
public void setupModule(SetupContext context) {
context.addDeserializers(new MyRefDeserializers());
context.addTypeModifier(new MyRefTypeModifier());
}
}
然后您需要使用 ObjectMapper
注册此模块。例如:
ObjectMapper = new ObjectMapper();
objectMapper.registerModule(new MyRefModule());
如果您使用 Spring Boot,您只需将模块公开为 @Bean
,它将自动注册到默认的 ObjectMapper
中。
关于java - 使用 ReferenceTypeDeserializer 与 Jackson & Spring 反序列化通用类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55166379/
我找不到关于 jackson 的ObjectMapper与其他映射器(例如dozer/mapStruct/modelMapping/etc)之间的区别的任何解释。所有文章都比较了dozer/mapSt
我正在使用Jackson来反序列化Kotlin数据类。我正在使用jackson-kotlin-module,但 jackson 却给我以下错误: Can not construct instance
我正在尝试将包从“com.fasterxml.jackson”重新定位到我自己的包(即“mypackage.com.fasterxml.jackson”),然后在我拥有的另一个 JAR 中使用它。 我
对于JSON对象,Subject: { "permissions":["foo", "bar"], ... } ...我想反序列化为: class Subject { priv
我正在使用 @JsonTypeInfo 和 @JsonSubTypes 来映射基于给定属性的解析子类。这是我想要解析的示例 JSON 的一个人为示例。 { "animals": [ { "
我们正在使用 dropwizard 版本 0.6.3。当我们尝试升级 0.7.0 版本时,我们在服务启动时收到此错误。 线程“main”中的异常 java.lang.VerifyError: clas
我正在尝试实现自定义解串器。因为我只想向默认反序列化器添加功能,所以我尝试在我的自定义反序列化器中存储默认反序列化器:我想使用默认反序列化 json,然后添加其他信息。 我正在尝试使用 BeanDes
我有一个这样的类(class): public class Person { private String name; public String getName(){ return
我有以下 Kotlin 数据类: data class TestObject( val boolField: Boolean, val stringField: Str
使用 Jackson 库,在 Eclipse 4.9.0 版本中出现以下错误 缺少工件 com.fasterxml.jackson.core:jackson-databind:bundle:2.9.6
我试图在我的应用程序中从azure实现keyvault,在为DefaultAzureCredentialBuilder()实现azure-identity:1.5.4 lib后,它会抛出链接错误,如下
我试图在我的应用程序中从azure实现keyvault,在为DefaultAzureCredentialBuilder()实现azure-identity:1.5.4 lib后,它会抛出链接错误,如下
我知道我们可以使用 Jackson MixIn 来重命名属性或忽略属性(参见示例 here )。但是可以添加属性吗? 添加的属性可以是: 一个常数(如版本号) 计算值(例如,如果源类具有 getWid
我有一个在 Wildfly 10 上运行的应用程序,它需要更新版本的 jackson。简单地更新 maven 依赖是行不通的。 Wildflys 自己的版本似乎干扰了... 有人有提示吗? 最佳答案
我在 Tomcat 休息应用程序中运行 Jersey 2.5.1 & Jackson。对于我最初将 POJO 简单地转换为 JSON 的用例,基本设置效果很好。集合很好地转换为 json 数组,如下所
有没有办法告诉 jackson 在序列化过程中忽略那些用非 jackson 注释注释的字段? 例如: @SomeAnnotation private String foo; 我知道有 jackson
我遇到了 jackson 序列化问题, map 中存在空值。显然,这是 Wildfly 9 使用的 Jackson 版本中的一个已知错误 ( https://issues.jboss.org/brow
给定一个像这样的 JSON 映射类: public class Person { @JsonProperty String getName() { ... } @JsonPro
如何让 Jackson 的 XMLMapper 在反序列化时读取根 xml 元素的名称? 我正在将输入 XML 反序列化为通用 Java 类、LinkedHashMap,然后反序列化为 JSON。我想
我对抽象类和 JSON 序列化和反序列化的对象引用有问题。抽象的问题如下所示: 我有一个由节点和边组成的图。每条边连接两个节点。节点可以是红色和绿色的。因此,有一个抽象类Node和两个派生类 RedN
我是一名优秀的程序员,十分优秀!