[英]How to disable Jackson from deserializing an Instant from epoch millis?
[英]How to restrict jackson from parsing millis to LocalDate in json request
我需要驗證 json 請求中的 LocalDate 字段。 我想要的是防止將數字反序列化為本地日期的 miilis。 這是示例:
我有一個實體:
public class Test {
@NotNull
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate birthDate;
//getter and setter of course
}
Jackson2ObjectMapperBuilder 配置:
@Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.serializationInclusion(JsonInclude.Include.NON_EMPTY);
builder.featuresToEnable(DeserializationFeature.READ_ENUMS_USING_TO_STRING);
builder.featuresToEnable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
builder.featuresToDisable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
builder.modulesToInstall(new JavaTimeModule());
return builder;
}
現在,如果我收到:
{
"birthDate": 1
}
結果是birthDate=1970-01-02
我可以通過將leniency
設置為 false 來做到這一點:
objectMapper.configOverride(LocalDate.class).setFormat(JsonFormat.Value.forLeniency(false));
objectMapper.configOverride(LocalDateTime.class).setFormat(JsonFormat.Value.forLeniency(false));
然后它通過拋出MismatchedInputException
來工作
但是我們服務的向后兼容性有點殘酷,因為我們需要將所有日期模式從“yyyy-MM-dd”更改為“uuuu-MM-dd”,我想知道是否有一些解決方案可以說 jackson “如果你在反序列化時看到數字或任何與模式不同的東西,拋出異常”
您可以編寫自定義 LocalDateDeserializer:
public class MyLocalDateDeserializer extends JsonDeserializer<LocalDate> implements ContextualDeserializer {
private LocalDateDeserializer defaultDeserializer = new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
public MyLocalDateDeserializer() {
super();
}
public MyLocalDateDeserializer(LocalDateDeserializer defaultDeserializer) {
super();
this.defaultDeserializer = defaultDeserializer;
}
@Override
public LocalDate deserialize(JsonParser parser, DeserializationContext context) throws IOException
{
if (StringUtils.isNumeric(parser.getText())) {
throw JsonMappingException.from(parser, "Not a String representation of Date ");
}
return defaultDeserializer.deserialize(parser, context);
}
@Override
public JsonDeserializer<?> createContextual(DeserializationContext ctxt,
BeanProperty property) throws JsonMappingException
{
JsonFormat.Value format = findFormatOverrides(ctxt, property, handledType());
return (format == null) ? this : new MyLocalDateDeserializer(new LocalDateDeserializer(DateTimeFormatter.ofPattern(format.getPattern())));
}
protected JsonFormat.Value findFormatOverrides(DeserializationContext ctxt,
BeanProperty prop, Class<?> typeForDefaults)
{
if (prop != null) {
return prop.findPropertyFormat(ctxt.getConfig(), typeForDefaults);
}
// even without property or AnnotationIntrospector, may have type-specific defaults
return ctxt.getDefaultPropertyFormat(typeForDefaults);
}
}
並在需要時注冊。
這是我的簡單測試:
@Test()
public void testObjectMapperForLocalDate() throws IOException {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addDeserializer(LocalDate.class, new MyLocalDateDeserializer());
builder.modulesToInstall(javaTimeModule);
ObjectMapper objectMapper = builder.build();
DateContainer container = objectMapper.readValue("{\r\n" +
" \"birthDate\": \"1999-01-01\"\r\n" +
"}", DateContainer.class);
System.out.println(container.getBirthDate());
}
@Test()
public void testFailObjectMapperForLocalDate() throws IOException {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addDeserializer(LocalDate.class, new MyLocalDateDeserializer());
builder.modulesToInstall(javaTimeModule);
ObjectMapper objectMapper = builder.build();
assertThrows(JsonMappingException.class, () -> {
DateContainer container = objectMapper.readValue("{\r\n" +
" \"birthDate\": 1\r\n" +
"}", DateContainer.class);
System.out.println(container.getBirthDate());
});
}
編輯
反序列化器使用模式
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.