我有一个使用此方法的休息控制器:
@RequestMapping(value = "", method = { RequestMethod.POST }, produces = { MediaType.APPLICATION_JSON_VALUE })
public ResponseEntity<?> add(@Valid @RequestBody MyModel myModel, Errors errors) {
...
return new ResponseEntity<SomeObject>(someObject, HttpStatus.OK);
}
在MyModel
中有一个字段isMeetingOrSale
,即enum(MeetingSaleFlag
):
public enum MeetingSaleFlag {
MEETING("MEETING"),
SALE("SALE");
private final String name;
private MeetingSaleFlag(String s) { name = s; }
public boolean equalsName(String otherName) {
return (otherName == null) ? false : name.equals(otherName);
}
public String toString() { return this.name; }
}
它可以映射具有字段"isMeetingOrSale" : "MEETING"
但是json中的值可能是"isMeetingOrSale" : ""
或完全缺失,所以在这种情况下我希望将字段映射为null。如果我将字段更改为Optional<MeetingSaleFlag>
我得到了
无法读取JSON:无法实例化类型的值[simple type, 来自String值的类
java.util.Optional<MeetingSaleFlag>
] ('会议');没有单字符串构造函数/工厂方法\\ n at [来源:java.io.PushbackInputStream@32b21158;行:17,专栏:18] (通过参考链:MyModel [\“isMeetingOrSale \”]);
所以问题是如何从json映射可选枚举?
答案 0 :(得分:4)
感谢Sotirios Delimanolis的评论,我能够解决这个问题。
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jdk8</artifactId>
</dependency>
作为依赖。
@Bean
@Primary
public ObjectMapper jacksonObjectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new Jdk8Module());
return mapper;
}
OR 执行此操作以注册jdk8模块
/**
* @return Jackson jdk8 module to be registered with every bean of type
* {@link ObjectMapper}
*/
@Bean
public Module jdk8JacksonModule() {
return new Jdk8Module();
}
自定义Jackson的另一种方法是将com.fasterxml.jackson.databind.Module类型的bean添加到您的上下文中。它们将在ObjectMapper类型的每个bean中注册,为您的应用程序添加新功能时提供全局机制来提供自定义模块。
这样做只会注册附加模块并保留Spring Boot提供的内置Jackson配置。
现在,当发送的json中缺少该属性时,它将映射为null
(这不是那么好。我期待它会给我一个可选项,我将能够使用.isPresent()
)。
如果它是一个空字符串("isMeetingOrSale" : ""
),杰克逊会返回错误:
无法读取JSON:无法构造实例 来自字符串值的MyModel&#39;&#39;:值不是 一个声明的枚举实例名称:[VAL1,VAL2]
对我来说很好看。
答案 1 :(得分:3)
这是我们代码库的一个例子:
@NotNull // You probably don't want this
@JsonSerialize(using=CountrySerializer.class)
@JsonDeserialize(using=CountryDeserializer.class)
private CountryCode country;
其中CountryCode是 complex 枚举(请参阅nv-i18n),这些是(de)从/到JSON序列化的类:
public class CountrySerializer extends JsonSerializer<CountryCode> {
@Override
public void serialize(CountryCode value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
jgen.writeString(value.getAlpha3()); // Takes the Alpha3 code
}
public Class<CountryCode> handledType() { return CountryCode.class; }
}
和
public class CountryDeserializer extends JsonDeserializer<CountryCode> {
@Override
public CountryCode deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
// You can add here the check whether the field is empty/null
return CountryCode.getByCode(jp.getText());
}
}
您可以使用 MeetingSaleFlag 而不是 CountryCode 轻松复制相同的方案。