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

时间:2018-07-03 03:47:01

标签: java spring-boot objectmapper

嗨,我尝试创建一个将请求参数接受为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

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

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]的值'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>

我想念什么吗? 谢谢您的宝贵时间。

2 个答案:

答案 0 :(得分:0)

  

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

我认为在这里您需要使用 JsonSerializer JsonDeserializer

因此,当请求发出时,您使用 JsonDeserializer ,它将把您的String格式的日期转换为所需的Date格式。这是代码,

@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;
    }

}

答案 1 :(得分:0)

问题是我在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);
}
}