在 ObjectMapper 中全局配置 JavaTimeModule 而不是使用@datetimeformat

Posted

技术标签:

【中文标题】在 ObjectMapper 中全局配置 JavaTimeModule 而不是使用@datetimeformat【英文标题】:Configure JavaTimeModule in ObjectMapper globally instead of using @datetimeformat 【发布时间】:2018-12-11 06:50:27 【问题描述】:

您好,我尝试创建一个控制器,它将接受请求参数作为 LocalDateTime。

ex: /api/actions?page=0&size=10&from=2018-05-02T20:20:20&to=2018-06-02T20:20:20

如果我使用下面的代码,在控制器上它可以工作:

@RequestParam(value = "from")
        @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
                LocalDateTime from,
        @RequestParam(value = "to")
        @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
                LocalDateTime to

但我想将@DateTimeFormat 移动到全局配置中,我选择了ObjectMapper:

我在配置中创建了一个 bean:

@Bean
public ObjectMapper jacksonObjectMapper() 
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
    JavaTimeModule javaTimeModule = new JavaTimeModule();
    javaTimeModule.addSerializer(
            LocalDateTime.class,
            new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(dateTimeFormat)));
    objectMapper.registerModule(javaTimeModule);
    return objectMapper;

然后试试

@Bean
public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) 
    ObjectMapper objectMapper = builder.createXmlMapper(false).build();
    objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
    JavaTimeModule javaTimeModule = new JavaTimeModule();
    javaTimeModule.addSerializer(
            LocalDateTime.class,
            new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(dateTimeFormat)));
    objectMapper.registerModule(javaTimeModule);
    return objectMapper;

这是 dateTimeFormat 值:yyyy-MM-dd'T'HH:mm:ss.SS

以上两种方式都不起作用,它说:

class org.springframework.web.method.annotation.MethodArgumentTypeMismatchException:无法将“java.lang.String”类型的值转换为所需的“java.time.LocalDateTime”类型;嵌套异常是 org.springframework.core.convert.ConversionFailedException: 无法从类型 [java.lang.String] 转换为类型 [@org.springframework.web.bind.annotation.RequestParam java.time.LocalDateTime] for value '2018 -05-02T20:20:20';嵌套异常是 java.lang.IllegalArgumentException:值 [2018-05-02T20:20:20] 的解析尝试失败

我的杰克逊版本:

<dependency>
        <groupId>com.fasterxml.jackson.datatype</groupId>
        <artifactId>jackson-datatype-jsr310</artifactId>
        <version>2.8.8</version>
    </dependency>

我错过了什么吗? 感谢您的宝贵时间。

【问题讨论】:

检查这个答案。我已经回答了其他问题的解决方案:***.com/a/50128685/6703392 它不使用杰克逊,所以配置不会做任何事情。 问题是我在 requestParam 传递 LocalDateTime,但我使用的 ObjectMapper 仅适用于请求的正文。为了解决我的问题,我创建了新组件 LocalDateTimeConverter 并删除了 ObjectMapper 的 bean。在这里查看答案:***.com/a/51149932/9833606 【参考方案1】:

问题是我在 requestParam 中传递 LocalDateTime,但我使用的 ObjectMapper 仅适用于请求的正文。

为了解决我的问题,我创建了新组件 LocalDateTimeConverter 并删除了 ObjectMapper 的 bean。

@Component
public class LocalDateTimeConverter implements Converter<String, LocalDateTime> 
private final DateTimeFormatter formatter;

@Autowired
public LocalDateTimeConverter(@Value("$dateTime.format") String dateTimeFormat) 
    this.formatter = DateTimeFormatter.ofPattern(dateTimeFormat);


@Override
public LocalDateTime convert(String source) 
    if (source == null || source.isEmpty()) 
        return null;
    

    return LocalDateTime.parse(source, formatter);


【讨论】:

【参考方案2】:

class org.springframework.web.method.annotation.MethodArgumentTypeMismatchException:无法将“java.lang.String”类型的值转换为所需的“java.time.LocalDateTime”类型;嵌套异常是 org.springframework.core.convert.ConversionFailedException

我觉得这里你需要使用JsonSerializerJsonDeserializer

所以,当请求到来时,您使用 JsonDeserializer,它会将您的字符串格式的日期转换为所需的日期格式。这是一个代码,

@Component
public class DateDeSerializer extends JsonDeserializer<Date> 

    public final SimpleDateFormat formatter = new SimpleDateFormat("date format");

    @Override
    public Date deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException 
        if (jp.getCurrentToken().equals(JsonToken.VALUE_STRING)) 
            try 
                return formatter.parse(jp.getText());
             catch (ParseException e) 
                // throw exception 
            
        
        return null;
    

    @Override
    public Class<Date> handledType() 
        return Date.class;
    


要格式化您的响应,请使用 JsonSerializer。这是一个示例代码,

@Component
public class DateSerializer extends JsonSerializer<Date> 

    DateFormat formatter = new SimpleDateFormat("date format");

    @Override
    public void serialize(Date value, JsonGenerator gen, SerializerProvider serializers) throws IOException 
        gen.writeObject(formatter.format(value));
    

    @Override
    public Class<Date> handledType() 
        return Date.class;
    


【讨论】:

以上是关于在 ObjectMapper 中全局配置 JavaTimeModule 而不是使用@datetimeformat的主要内容,如果未能解决你的问题,请参考以下文章

配置Java AWS Lambda使用的Objectmapper

Spring Boot 自定义Jackson ObjectMapper

如何在 Spring Boot 中为 Camel 配置 Jackson ObjectMapper

RestAssured 不尊重 Quarkus 中的 ObjectMapper 配置

配置 Dropwizard ObjectMapper 以配置忽略未知

jackson中objectMapper的使用