使用 Jackson 反序列化枚举 [英] Deserializing an enum with Jackson
问题描述
我正在尝试使用 Jackson 2.5.4 反序列化枚举,但未能成功,而且我不太清楚我的情况.我的输入字符串是驼峰式大小写,我想简单地映射到标准的 Enum 约定.
I'm trying and failing to deserialize an enum with Jackson 2.5.4, and I don't quite see my case out there. My input strings are camel case, and I want to simply map to standard Enum conventions.
@JsonFormat(shape = JsonFormat.Shape.STRING)
public enum Status {
READY("ready"),
NOT_READY("notReady"),
NOT_READY_AT_ALL("notReadyAtAll");
private static Map<String, Status> FORMAT_MAP = Stream
.of(Status.values())
.collect(toMap(s -> s.formatted, Function.<Status>identity()));
private final String formatted;
Status(String formatted) {
this.formatted = formatted;
}
@JsonCreator
public Status fromString(String string) {
Status status = FORMAT_MAP.get(string);
if (status == null) {
throw new IllegalArgumentException(string + " has no corresponding value");
}
return status;
}
}
我也在 getter 上尝试了 @JsonValue
无济于事,这是我在别处看到的一个选项.他们都炸了:
I've also tried @JsonValue
on a getter to no avail, which was an option I saw reported elsewhere. They all blow up with:
com.fasterxml.jackson.databind.exc.InvalidFormatException: Can not construct instance of ...Status from String value 'ready': value not one of declared Enum instance names: ...
我做错了什么?
推荐答案
从 Jackson 2.6 开始,您可以在枚举的每个元素上使用 @JsonProperty
指定其序列化/反序列化值(参见此处):
Starting from Jackson 2.6, you can use @JsonProperty
on each element of the enum to specify its serialization/deserialization value (see here):
public enum Status {
@JsonProperty("ready")
READY,
@JsonProperty("notReady")
NOT_READY,
@JsonProperty("notReadyAtAll")
NOT_READY_AT_ALL;
}
<小时>
(这个答案的其余部分对于旧版本的 Jackson 仍然有效)
(The rest of this answer is still valid for older versions of Jackson)
您应该使用 @JsonCreator
来注释接收 String
参数的静态方法.这就是杰克逊所说的工厂方法:
You should use @JsonCreator
to annotate a static method that receives a String
argument. That's what Jackson calls a factory method:
public enum Status {
READY("ready"),
NOT_READY("notReady"),
NOT_READY_AT_ALL("notReadyAtAll");
private static Map<String, Status> FORMAT_MAP = Stream
.of(Status.values())
.collect(Collectors.toMap(s -> s.formatted, Function.identity()));
private final String formatted;
Status(String formatted) {
this.formatted = formatted;
}
@JsonCreator // This is the factory method and must be static
public static Status fromString(String string) {
return Optional
.ofNullable(FORMAT_MAP.get(string))
.orElseThrow(() -> new IllegalArgumentException(string));
}
}
这是测试:
ObjectMapper mapper = new ObjectMapper();
Status s1 = mapper.readValue(""ready"", Status.class);
Status s2 = mapper.readValue(""notReadyAtAll"", Status.class);
System.out.println(s1); // READY
System.out.println(s2); // NOT_READY_AT_ALL
由于工厂方法需要一个 String
,因此您必须对字符串使用 JSON 有效语法,即引用值.
As the factory method expects a String
, you have to use JSON valid syntax for strings, which is to have the value quoted.
这篇关于使用 Jackson 反序列化枚举的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!