gpt4 book ai didi

java - 即使我添加自定义的反序列化器,Jackson 也无法将枚举反序列化为对象

转载 作者:搜寻专家 更新时间:2023-10-31 19:32:50 25 4
gpt4 key购买 nike

我想使用 Jackson JSON 序列化/反序列化包含枚举对象的类。我的类(class)是:

class Bar {

@JsonProperty("rateType")
@JsonDeserialize(using = ReturnedRateTypeDeserializer.class)
private ReturnedRateType rateType;

public ReturnedRateType getRateType() {
return rateType;
}

public void setRateType(ReturnedRateType rateType) {
this.rateType = rateType;
}
}

枚举类 ReturnedRateType 定义为:

@JsonFormat(shape = JsonFormat.Shape.OBJECT)
public enum ReturnedRateType {
AA("AA"),
BB("BB"),
CC("CC");

@JsonProperty("value")
private String value;

ReturnedRateType(String value) {
this.value = value;
}

@JsonCreator
public static ReturnedRateType fromValue(final String value) {
if (value != null) {
for (ReturnedRateType type : ReturnedRateType.values()) {
if (value.equalsIgnoreCase(type.value)) {
return type;
}
}
}
return null;
}
}

如您所见,我添加了 @JsonFormat 注释以告知 Jackson 将此枚举序列化为 POJO,并添加了 @JsonCreator 注释以从给定字符串获取静态工厂方法枚举对象。由于 Jackson 只能序列化但不能从对象表示反序列化为枚举,因此我为枚举 ReturnedRateType 添加了以下自定义反序列化器:

public class ReturnedRateTypeDeserializer extends JsonDeserializer<ReturnedRateType> {

@Override
public ReturnedRateType deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
ReturnedRateType type = ReturnedRateType.fromValue(jp.getValueAsString());
if(type != null)
return type;
throw new JsonMappingException("invalid value for ReturnedRateType");
}
}

但是当我测试从 JSON 字符串到枚举的反序列化时,我得到了错误。 JSON 字符串是:

{"rateType": {"value": "AA"}}

我的测试代码是:

@Test
public void RateTypeToEnum() {
String json = "{\"rateType\": {\"value\": \"AA\"}}";
System.out.println(json);
ObjectMapper mapper = new ObjectMapper();
Bar bar = null;
try {
bar = mapper.readValue(json, Bar.class);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(bar.getRateType());
}

我希望看到的输出应该是 AA。但是我自定义的反序列化器 ReturnedRateTypeDeserializer 中的 jp.getValueAsString() 在执行期间为 null:

ReturnedRateType type = ReturnedRateType.fromValue(jp.getValueAsString());  //jp.getValueAsString() is null here!

因此它返回错误。那么这里有什么问题呢?

最佳答案

根据关于 JsonFormat 注释的 Jackson 2.5.X 文档,Shape.Object 不适用于枚举反序列化:

  • 枚举:形状 JsonFormat.Shape.STRING 和 JsonFormat.Shape.NUMBER 可以用于在数字(索引)和文本(名称或toString());但也可以使用 JsonFormat.Shape.OBJECT序列化(但不反序列化)。

我会让 JsonCreator 静态方法接受一个 JsonNode 并从中读取字符串值。

请注意,自 2.5.X 起这将起作用。在早期版本中,您需要编写自定义解串器。这是一个例子:

public class JacksonEnumObjectShape {
@JsonFormat(shape = JsonFormat.Shape.OBJECT)
@JsonDeserialize(using = ReturnedRateTypeDeserializer.class)
public enum ReturnedRateType {
AA("AA"),
BB("BB"),
CC("CC");

@JsonProperty("value")
private String value;

ReturnedRateType(String value) {
this.value = value;
}

@JsonCreator
public static ReturnedRateType fromValue(final JsonNode jsonNode) {

for (ReturnedRateType type : ReturnedRateType.values()) {
if (type.value.equals(jsonNode.get("value").asText())) {
return type;
}
}
return null;
}
}
// can be avoided since 2.5
public static class ReturnedRateTypeDeserializer extends JsonDeserializer<ReturnedRateType> {

@Override
public ReturnedRateType deserialize(
final JsonParser jp,
final DeserializationContext ctxt) throws IOException {
final JsonNode jsonNode = jp.readValueAsTree();
return ReturnedRateType.fromValue(jsonNode);
}
}

public static void main(String[] args) throws IOException {
final ObjectMapper mapper = new ObjectMapper();
final String json = mapper.writeValueAsString(ReturnedRateType.AA);
System.out.println(json);
System.out.println(mapper.readValue(json, ReturnedRateType.class));
}
}

输出:

{"value":"AA"}
AA

关于java - 即使我添加自定义的反序列化器,Jackson 也无法将枚举反序列化为对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29566177/

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