使用 Jackson 反序列化枚举字段
Deserialise enum field with Jackson
我有一个简单的枚举Days
public enum Days {
@JsonProperty("Monday")
MONDAY("Monday"),
@JsonProperty("Tuesday")
TUESDAY("Tuesday");
private String day;
Days(String day) {
this.day = day;
}
@JsonValue
public String getDay() {
return day;
}
}
和一个classEvent
public class Event {
private Days day;
private String name;
@JsonCreator
public Event(@JsonProperty("day") Days day,
@JsonProperty("name") String name) {
this.day = day;
this.name = name;
}
public Days getDay() {
return day;
}
public String getName() {
return name;
}
}
我正在使用 Jackson 2.9, 表明使用 @JsonProperty
应该足够了,但是我很难反序列化它:
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
Event event = new Event(Days.MONDAY, "Birthday");
String serialisedEvent = objectMapper.writeValueAsString(event);
System.out.println(serialisedEvent);
// {"day":"Monday","name":"Birthday"}
Event deserialisedEvent = objectMapper.convertValue(serialisedEvent, Event.class);
// Exception in thread "main" java.lang.IllegalArgumentException: Cannot construct instance of `xyz.blabla.Event` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('{"day":"Monday","name":"Birthday"}')
// at [Source: UNKNOWN; line: -1, column: -1]
// at com.fasterxml.jackson.databind.ObjectMapper._convert(ObjectMapper.java:3750)
System.out.println(deserialisedEvent.getDay());
}
我在 Spring Boot 2 项目中使用 Java 11 和 Jackson 2.9。我怎样才能完成这项工作?
您没有默认构造函数,但有一个 arg 构造函数。
你必须用 @JsonCreator
注释它,以便 Jackson 使用它反序列化 JSON :
@JsonCreator
public Event(Days day, String name) {
this.day = day;
this.name = name;
}
要将 Java 对象序列化为 JSON,Jackson 不使用构造函数,因为它不会创建 java 实例,而只是使用 getter 来检索它的属性。所以它起作用了。
但是要将 JSON 反序列化为 Java 对象,Jackson 需要实例化目标 class。默认情况下,它会查找无参数构造函数。
另请注意,如果您使用 ParameterNamesModule
,则不需要使用 @JsonProperty("...")
注释构造函数参数,例如:
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new ParameterNamesModule());
Spring Boot 2 为您提供它,因为您依赖 Jackson。
这里你需要它,因为你没有使用 Spring Boot 的 Mapper 布线,而是你自己实例化它。
以及位于枚举中的 @JsonProperty
注释也不需要:
public enum Days {
@JsonProperty("Monday")
MONDAY("Monday"),
@JsonProperty("Tuesday")
TUESDAY("Tuesday");
//...
}
它允许更改枚举的序列化输出,但实际上您不需要更改它,因为您将其映射到当前用于枚举 Jackson 映射的 day
字段值...
调用了Jackson反序列化方法readValue
。
convertValue
的目的不同 — 它 序列化 一个对象(可能是一个字符串 — 它会变成一个 JSON-string-literal then) 首先,然后将结果反序列化为目标类型的对象。
以下应该有效:
Event deserialisedEvent = objectMapper.readValue(serialisedEvent, Event.class);
为了补充这个答案,我在互联网上搜索如何添加一次作为枚举值(并用破折号保存)。注意:枚举不允许破折号。我通过简单地添加
来解决这个问题
@JsonProperty("ONE-TIME")
枚举字段声明上方。
我有一个简单的枚举Days
public enum Days {
@JsonProperty("Monday")
MONDAY("Monday"),
@JsonProperty("Tuesday")
TUESDAY("Tuesday");
private String day;
Days(String day) {
this.day = day;
}
@JsonValue
public String getDay() {
return day;
}
}
和一个classEvent
public class Event {
private Days day;
private String name;
@JsonCreator
public Event(@JsonProperty("day") Days day,
@JsonProperty("name") String name) {
this.day = day;
this.name = name;
}
public Days getDay() {
return day;
}
public String getName() {
return name;
}
}
我正在使用 Jackson 2.9,@JsonProperty
应该足够了,但是我很难反序列化它:
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
Event event = new Event(Days.MONDAY, "Birthday");
String serialisedEvent = objectMapper.writeValueAsString(event);
System.out.println(serialisedEvent);
// {"day":"Monday","name":"Birthday"}
Event deserialisedEvent = objectMapper.convertValue(serialisedEvent, Event.class);
// Exception in thread "main" java.lang.IllegalArgumentException: Cannot construct instance of `xyz.blabla.Event` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('{"day":"Monday","name":"Birthday"}')
// at [Source: UNKNOWN; line: -1, column: -1]
// at com.fasterxml.jackson.databind.ObjectMapper._convert(ObjectMapper.java:3750)
System.out.println(deserialisedEvent.getDay());
}
我在 Spring Boot 2 项目中使用 Java 11 和 Jackson 2.9。我怎样才能完成这项工作?
您没有默认构造函数,但有一个 arg 构造函数。
你必须用 @JsonCreator
注释它,以便 Jackson 使用它反序列化 JSON :
@JsonCreator
public Event(Days day, String name) {
this.day = day;
this.name = name;
}
要将 Java 对象序列化为 JSON,Jackson 不使用构造函数,因为它不会创建 java 实例,而只是使用 getter 来检索它的属性。所以它起作用了。 但是要将 JSON 反序列化为 Java 对象,Jackson 需要实例化目标 class。默认情况下,它会查找无参数构造函数。
另请注意,如果您使用 ParameterNamesModule
,则不需要使用 @JsonProperty("...")
注释构造函数参数,例如:
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new ParameterNamesModule());
Spring Boot 2 为您提供它,因为您依赖 Jackson。
这里你需要它,因为你没有使用 Spring Boot 的 Mapper 布线,而是你自己实例化它。
以及位于枚举中的 @JsonProperty
注释也不需要:
public enum Days {
@JsonProperty("Monday")
MONDAY("Monday"),
@JsonProperty("Tuesday")
TUESDAY("Tuesday");
//...
}
它允许更改枚举的序列化输出,但实际上您不需要更改它,因为您将其映射到当前用于枚举 Jackson 映射的 day
字段值...
调用了Jackson反序列化方法readValue
。
convertValue
的目的不同 — 它 序列化 一个对象(可能是一个字符串 — 它会变成一个 JSON-string-literal then) 首先,然后将结果反序列化为目标类型的对象。
以下应该有效:
Event deserialisedEvent = objectMapper.readValue(serialisedEvent, Event.class);
为了补充这个答案,我在互联网上搜索如何添加一次作为枚举值(并用破折号保存)。注意:枚举不允许破折号。我通过简单地添加
来解决这个问题@JsonProperty("ONE-TIME")
枚举字段声明上方。