与杰克逊一起沙漠化枚举字段



我有一个简单的枚举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;
}
}

和CCD_ 2类

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());
}

我在SpringBoot2项目中使用Java11和Jackson2.9。我怎样才能做到这一点?

Jackson反序列化方法称为readValue

convertValue的用途不同——它首先序列化对象(可能是字符串——然后它将变成JSON字符串文字),然后将结果反序列化为目标类型的对象。

以下内容应该有效:

Event deserialisedEvent = objectMapper.readValue(serialisedEvent, Event.class);

您没有默认构造函数,但有一个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需要实例化目标类。默认情况下,它会查找无参数构造函数。

还要注意,如果使用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字段值。。。

为了补充这个答案,我在互联网上搜索了如何将ONE-TIME添加为枚举值(并用破折号保存)。注意:枚举不允许使用破折号。我通过简单地添加来解决这个问题

@JsonProperty("ONE-TIME")

在枚举字段声明上方。

相关内容

  • 没有找到相关文章

最新更新