jwi*_*ner 50 java json jackson
我正在尝试并且没有用Jackson 2.5.4反序列化枚举,我在那里看不到我的情况.我的输入字符串是驼峰式的,我想简单地映射到标准的Enum约定.
@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;
}
}
Run Code Online (Sandbox Code Playgroud)
我也尝试过@JsonValue一个无用的吸气剂,这是我在别处看到的一个选项.他们都爆炸了:
com.fasterxml.jackson.databind.exc.InvalidFormatException: Can not construct instance of ...Status from String value 'ready': value not one of declared Enum instance names: ...
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么?
Fed*_*ner 97
编辑:从Jackson 2.6开始,您可以使用@JsonProperty枚举的每个元素来指定其序列化/反序列化值(请参阅此处):
public enum Status {
@JsonProperty("ready")
READY,
@JsonProperty("notReady")
NOT_READY,
@JsonProperty("notReadyAtAll")
NOT_READY_AT_ALL;
}
Run Code Online (Sandbox Code Playgroud)
(这个答案的其余部分仍然适用于旧版本的杰克逊)
您应该使用@JsonCreator注释接收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(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));
}
}
Run Code Online (Sandbox Code Playgroud)
这是测试:
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
Run Code Online (Sandbox Code Playgroud)
正如工厂方法所期望的那样String,您必须对字符串使用JSON有效语法,即引用值.
小智 9
@JsonCreator
public static Status forValue(String name)
{
return EnumUtil.getEnumByNameIgnoreCase(Status.class, name);
}
Run Code Online (Sandbox Code Playgroud)
添加此静态方法将解决您的反序列化问题
这可能是一种更快的方法:
public enum Status {
READY("ready"),
NOT_READY("notReady"),
NOT_READY_AT_ALL("notReadyAtAll");
private final String formatted;
Status(String formatted) {
this.formatted = formatted;
}
@Override
public String toString() {
return formatted;
}
}
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
ObjectReader reader = mapper.reader(Status.class);
Status status = reader.with(DeserializationFeature.READ_ENUMS_USING_TO_STRING).readValue("\"notReady\"");
System.out.println(status.name()); // NOT_READY
}
Run Code Online (Sandbox Code Playgroud)
对于正在搜索具有整数 json 属性的枚举的人。这是对我有用的:
enum class Status (private val code: Int) {
PAST(0),
LIVE(2),
UPCOMING(1);
companion object {
private val codes = Status.values().associateBy(Status::code)
@JvmStatic @JsonCreator fun from (value: Int) = codes[value]
}
}
Run Code Online (Sandbox Code Playgroud)
小智 5
@JsonCreator(mode = JsonCreator.Mode.DELEGATING)是我的解决方案。
https://github.com/FasterXML/jackson-module-kotlin/issues/336#issuecomment-630587525