gpt4 book ai didi

java - 如何基于公共(public)字段使用 Jackson 抽象反序列化不同的枚举类型?

转载 作者:搜寻专家 更新时间:2023-10-31 20:33:45 24 4
gpt4 key购买 nike

问题:

我正在使用 Jackson 反序列化与它们在代码中的名称不匹配的 enum,下面是一个 json 示例。

{
"thing1": {"foo": "cool-guy"},
"thing2": {"foo": "loser-face"}
}

这里是enum,稍后我会解释interface

enum Foo implements HasText {
COOL_GUY("cool-guy"), LOSER_FACE("loser-face"), // etc...

private String text;

private Foo(String text) {
this.text = text;
}

@Override
public String getText() {
return text;
}
}

我知道如何为每个 enum 单独 解决这个问题,方法是制作反序列化器(如下)和注释 @JsonDeserialize(using = FooDeserializer .class) 关于 foo 的 setter 方法。

public class FooDeserializer extends JsonDeserializer<Enum<Foo>> {
@Override
public Foo deserialize(JsonParser p, DeserializationContext context) throws Exception {

if (p.getCurrentToken().equals(JsonToken.VALUE_STRING)) {
String jsonText = p.getText();
Stream<Foo> stream = Arrays.asList(Foo.values()).stream();
return stream.filter(a -> a.getText().equals(jsonText.toLowerCase())).findAny().get();
}

throw context.mappingException(Foo.class);
}
}

问题:

有没有办法抽象地做到这一点?这就是为什么我将 HasText interface 添加到我所有的枚举中,希望有一种方法可以做这样的事情:

public class EnumWithTextDeserializer<T extends Enum<T> & HasText> extends JsonDeserializer<T> {

@Override
public T deserialize(JsonParser p, DeserializationContext context) throws Exception {
if (p.getCurrentToken().equals(JsonToken.VALUE_STRING)) {
final String jsonText = p.getText();
final Stream<T> stream = Arrays.asList(runtimeClass().getEnumConstants()).stream();
return stream.filter(a -> a.getText().equals(jsonText.toLowerCase())).findAny().get();
}
throw context.mappingException(runtimeClass());
}

@SuppressWarnings("unchecked")
private Class<T> runtimeClass() {
ParameterizedType superclass = (ParameterizedType) getClass().getGenericSuperclass();
return (Class<T>) superclass.getActualTypeArguments()[0];
}
}

编译不会让我用这个类注释 setter 方法 (@JsonDeserialize(using = EnumWithTextDeserializer.class)) 因为

Type mismatch: cannot convert from Class<EnumWithTextDeserializer> to Class<? extends JsonDeserializer<?>>".

真的,我只想根据 getText() 方法反序列化这些 enum

最佳答案

为了反序列化,您可以使用 @JsonValue 指定您的字符串值。

public enum FooEnum implements WithText {
AWESOME("awesome-rad"),
NARLY("totally-narly");

private final String text;

FooEnum(String text) {
this.text = text;
}

@Override
@JsonValue
public String getText() {
return text;
}

}

然后执行这段代码进行序列化/反序列化

    ImmutableMap<String, FooEnum> map = ImmutableMap.of("value", FooEnum.AWESOME, "value2", FooEnum.NARLY);
final String value;
try {
value = objectMapper.writeValueAsString(map);
} catch (JsonProcessingException e) {
throw Throwables.propagate(e);
}

Map<String, FooEnum> read;
try {
read = objectMapper.readValue(value, new TypeReference<Map<String, FooEnum>>() {});
} catch (IOException e) {
throw Throwables.propagate(e);
}

我得到:

read = {LinkedHashMap@4627}  size = 2
0 = {LinkedHashMap$Entry@4631} "value1" -> "AWESEOME"
1 = {LinkedHashMap$Entry@4632} "value2" -> "NARLY"

关于java - 如何基于公共(public)字段使用 Jackson 抽象反序列化不同的枚举类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29720532/

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