微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

是否有 Spring Boot 标志来禁用随时间对 LocalDate 值进行宽松的 Jackson 解析?

如何解决是否有 Spring Boot 标志来禁用随时间对 LocalDate 值进行宽松的 Jackson 解析?

Spring Boot 认允许 LocalDate 中的日期和日期时间值。

例如对于以下 DTO:

public class Person {

  private LocalDate birthDate;

  //getter & setters
}

以下两种情况都是可以接受的:

{
  "birthDate" : "2021-07-24"
}
{
  "birthDate" : "2021-07-24T17:00:00Z"
}

Jackson 有一个 lenient 标志,可以设置为拒绝带有时间的日期:

@JsonFormat(pattern="uuuu-MM-dd",lenient = OptBoolean.FALSE)
private LocalDate birthDate;

是否有对应的Spring Boot应用属性标志,可以设置全局应用到所有LocalDate字段,这样注解就不需要每一个LocalDate字段都加定义一个this?

这样的自定义解串器

解决方法

我自己在本地对此进行了测试,看来 input 注释元素不是导致日期时间值被拒绝的原因,而是 lenient 元素的存在。因此,这足以拒绝日期时间值:

format

也就是说,Jackson 2.13 正在改变 @JsonFormat(pattern="uuuu-MM-dd") private LocalDate birthDate; 标志的行为,这样当日期时间值为 false (jackson-modules-java8#212) 时将被拒绝。对于 Jackson 2.13(在撰写本文时尚未发布),以下内容也足以使用默认的 lenient ISO 格式拒绝日期时间值:

LocalDate

至于您关于配置日期格式的全局标志的主要问题,我在 Jackson 中没有看到任何功能标志来全局配置它,这排除了直接配置 @JsonFormat(lenient = OptBoolean.FALSE) private LocalDate birthDate; spring.jackson 属性具有内置的 Jackson 功能。

有一个 spring.jackson.date-format 应用程序属性,看起来可以用于此目的。但是,进一步研究该属性,它似乎仅用于使用 java.text.DateFormat 的旧 Java 日期类型,而不用于新的 ObjectMapper 类型。这在 Jackson 问题 #3132 中有简要说明:

不幸的是,Java 8 日期/时间格式字符串应用程序与“旧 JDK”类型不同; java.time 根本无法使用。

Spring Boot 问题 #27547 是一项功能请求,用于添加标志以通过应用程序属性全局配置 DateFormat 设置。

,

我不知道是否有这样的属性,但您可以通过配置 ObjectMapper 来实现这一点。配置类 (like here) 只需要几行代码,但如果还有其他需要全局配置的内容,那么最好使用它。

看看这个配置类:

@Configuration
public class JacksonConfiguration {
    public static final String LOCAL_DATE_PATTERN = "yyyy-MM-dd";

    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper mapper = new ObjectMapper();
        JavaTimeModule timeModule = new JavaTimeModule();
        timeModule.addDeserializer(LocalDate.class,new LocalDateDeserializer(DateTimeFormatter
                        .ofPattern(LOCAL_DATE_PATTERN)));
        mapper.registerModule(timeModule);
        return mapper;
    }
}

Jackson 使用 JavaTimeModule 来解析 LocalDate(和 LocalDateTime)。 JavaTimeModule 包括默认反序列化器,似乎没有直接访问它们的方法,因此技巧是替换反序列化 LocalDate 的那个。如果在给定的 LocalDate(Time) 内也有时间,在示例中将模式显式设置为 1 将导致解析错误。

如您所见,似乎需要自定义反序列化器,但将其设置在配置类上并不是什么大问题。

,

对于 2.12 之前的 Jackson 版本(截至撰写本文时的当前发布版本),将 lenient 标志设置为 false 实际上不会导致 Jackson 拒绝时间部分。 Jackson 2.13 将根据 jackson-modules-java8#212 对此进行更改,以便将 lenient 标志设置为 false 将导致带有时间的日期被拒绝。

据我所知,目前没有可用于禁用默认宽大处理的 Spring Boot 属性,尽管发出 #27547 请求添加了一个。但是,可以使用 ObjectMapper.setDefaultLeniency(Boolean b)ObjectMapper 中配置默认​​宽大设置。因此,一旦 Jackson 2.13 发布,就可以在提供的 ObjectMapper bean 上设置此标志,以实现拒绝带有时间组件的日期的预期目标。

禁用此功能的最直接方法可能是使用自定义 Jackson2ObjectMapperBuilderCustomizer 来配置 ObjectMapper

@Configuration
public class CustomizedJacksonConfiguration {
    @Bean
    public Jackson2ObjectMapperBuilderCustomizer nonLenientObjectMapperBuilderCustomizer() {
        return builder -> builder.postConfigurer(
                objectMapper -> objectMapper.setDefaultLeniency(false));
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。