You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jackson将VersementDTO转为JSON时日期格式化及反序列化问题求助

Java LocalDateTime字段的Jackson序列化/反序列化问题处理

问题场景

需要将Java对象VersementDTO转换为名为Historique的JSON字符串,该DTO包含LocalDateTime类型的日期字段,存在两个问题:

  1. Jackson默认将LocalDateTime序列化为嵌套对象形式,不符合期望的2007/02/21 15:21:24格式
  2. 反序列化时出现错误,无法将字符串2007-02-07T15:21:24转换为LocalDateTime类型,报错信息如下:

org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type java.time.LocalDateTime from String "2007-02-07T15:21:24": Failed to deserialize java.time.LocalDateTime: (java.time.format.DateTimeParseException) Text '2007-02-07T15:21:24' could not be parsed at index 10; nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type java.time.LocalDateTime from String "2007-02-07T15:21:24": Failed to deserialize java.time.LocalDateTime: (java.time.format.DateTimeParseException) Text '2007-02-07T15:21:24' could not be parsed at index 10
at [Source: (PushbackInputStream); line: 1, column: 95] (through reference chain: aws.lbackend.dto.VersementDTO["dateValidation"])

当前使用的转换代码

public static String historizeInJson(VersementDTO pojo) {

    SimpleDateFormat df = new SimpleDateFormat("dd-MM-yyyy hh:mm");
    df.setTimeZone(TimeZone.getTimeZone("UTC"));

    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.setDateFormat(new StdDateFormat().withColonInTimeZone(true));

    objectMapper.configure(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS, false);
    objectMapper.configure(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS, false);
    try {
        String jsVDTO = objectMapper.writeValueAsString(pojo);
        //System.out.print("json dz : "+ jsVDTO);
        return jsVDTO;
    } catch (JsonProcessingException e) {
            LOGGER.info("failed conversion: Pfra object to Json", e);
        return null;
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

问题原因

当前代码使用的SimpleDateFormat、StdDateFormat都是针对Java旧日期类型(java.util.Date)的配置,无法作用于Java 8+的新时间API类型(LocalDateTime),需要使用Jackson专门的jackson-datatype-jsr310模块来支持这类类型的序列化和反序列化。

解决步骤

  1. 引入依赖:确保项目中引入了jackson-datatype-jsr310模块(Maven示例):
<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
    <version>你的Jackson版本号</version>
</dependency>
  1. 修改ObjectMapper配置:注册JavaTimeModule,并自定义LocalDateTime的序列化/反序列化格式,同时兼容反序列化时的ISO格式(即带T的字符串):

修改后的完整代码

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.TimeZone;

public static String historizeInJson(VersementDTO pojo) {
    // 定义期望的日期输出格式
    DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
    // 定义兼容反序列化的多格式规则:同时支持目标格式和带T的ISO格式
    DateTimeFormatter deserializeFormatter = DateTimeFormatter.ofPattern("[yyyy/MM/dd HH:mm:ss][yyyy-MM-dd'T'HH:mm:ss]");

    ObjectMapper objectMapper = new ObjectMapper();
    // 注册JavaTimeModule以支持Java 8+时间类型
    JavaTimeModule timeModule = new JavaTimeModule();
    // 配置LocalDateTime序列化器:输出指定格式的字符串
    timeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(outputFormatter));
    // 配置LocalDateTime反序列化器:兼容两种输入格式
    timeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(deserializeFormatter));
    
    objectMapper.registerModule(timeModule);
    // 统一设置时区为UTC
    objectMapper.setTimeZone(TimeZone.getTimeZone("UTC"));
    // 关闭时间戳输出,确保日期以字符串形式返回
    objectMapper.configure(com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
    objectMapper.configure(com.fasterxml.jackson.databind.SerializationFeature.FAIL_ON_EMPTY_BEANS, false);

    try {
        return objectMapper.writeValueAsString(pojo);
    } catch (JsonProcessingException e) {
        LOGGER.info("failed conversion: Pfra object to Json", e);
        return null;
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

代码说明

  • JavaTimeModule:Jackson专门为Java 8+时间API提供的模块,必须注册才能处理LocalDateTime等新时间类型
  • LocalDateTimeSerializer:自定义序列化逻辑,将LocalDateTime转为指定的yyyy/MM/dd HH:mm:ss格式字符串
  • LocalDateTimeDeserializer:使用带方括号的格式模式,同时兼容目标格式和带T的ISO格式输入,直接解决反序列化报错问题
  • 统一设置UTC时区:确保日期处理的时区一致性,避免跨时区导致的日期偏差

内容的提问来源于stack exchange,提问作者Organon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 23:25:19