gpt4 book ai didi

java - 如何在 Jackson 中为泛型创建自定义反序列化器?

转载 作者:太空狗 更新时间:2023-10-29 22:49:33 28 4
gpt4 key购买 nike

想象一下以下场景:

class <T> Foo<T> {
....
}

class Bar {
Foo<Something> foo;
}

我想为 Foo 编写自定义 Jackson 反序列化器。为此(例如,为了反序列化具有 Bar 属性的 Foo<Something> 类),我需要知道 Foo<T> 的具体类型, 用于 Bar ,在反序列化时(例如,我需要知道 T 在这种特殊情况下是 Something)。

如何编写这样的反序列化器?应该可以做到这一点,因为 Jackson 使用类型化的集合和映射来做到这一点。

说明:

似乎有两个部分可以解决问题:

1) 获取声明的属性类型 foo里面Bar并用它来反序列化 Foo<Somehting>

2) 在反序列化时发现我们正在反序列化属性 foo内部类Bar为了成功完成步骤 1)

如何完成 1 和 2?

最佳答案

您可以实现自定义 JsonDeserializer 对于您的通用类型,它也实现了 ContextualDeserializer .

例如,假设我们有以下包含通用值的简单包装器类型:

public static class Wrapper<T> {
public T value;
}

我们现在想要反序列化如下所示的 JSON:

{
"name": "Alice",
"age": 37
}

进入类的实例,如下所示:

public static class Person {
public Wrapper<String> name;
public Wrapper<Integer> age;
}

实现 ContextualDeserializer允许我们为 Person 中的每个字段创建一个特定的反序列化器类,基于字段的泛型类型参数。这允许我们将名称反序列化为字符串,将年龄反序列化为整数。

完整的反序列化器如下所示:

public static class WrapperDeserializer extends JsonDeserializer<Wrapper<?>> implements ContextualDeserializer {
private JavaType valueType;

@Override
public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException {
JavaType wrapperType = property.getType();
JavaType valueType = wrapperType.containedType(0);
WrapperDeserializer deserializer = new WrapperDeserializer();
deserializer.valueType = valueType;
return deserializer;
}

@Override
public Wrapper<?> deserialize(JsonParser parser, DeserializationContext ctxt) throws IOException {
Wrapper<?> wrapper = new Wrapper<>();
wrapper.value = ctxt.readValue(parser, valueType);
return wrapper;
}
}

最好看看createContextual首先是这里,因为 Jackson 将首先调用它。我们从 BeanProperty 中读取字段的类型(例如 Wrapper<String> ),然后提取第一个通用类型参数(例如 String )。然后我们创建一个新的反序列化器并将内部类型存储为 valueType .

一次deserialize在这个新创建的反序列化器上被调用,我们可以简单地要求 Jackson 将值反序列化为内部类型而不是整个包装类型,并返回一个新的 Wrapper。包含反序列化的值。

为了注册这个自定义反序列化器,我们需要创建一个包含它的模块,并注册该模块:

SimpleModule module = new SimpleModule()
.addDeserializer(Wrapper.class, new WrapperDeserializer());

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(module);

如果我们随后尝试反序列化上面的示例 JSON,我们可以看到它按预期工作:

Person person = objectMapper.readValue(json, Person.class);
System.out.println(person.name.value); // prints Alice
System.out.println(person.age.value); // prints 37

Jackson documentation 中有一些关于上下文反序列化器如何工作的更多细节。 .

关于java - 如何在 Jackson 中为泛型创建自定义反序列化器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36159677/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com