LocalDateTime的序列化和反序列化

背景

最近定位出一个LocalDateTime序列化相关的问题,简单记录一下。本文重点介绍Jackson对LocalDateTime的序列化和反序列化,并结合Spring应用场景进行介绍。

1.LocalDateTime与字符串转换

可以通过DateTimeFormatter实现LocalDateTime与字符串的相互转换,如下所示:

private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

private static String getFormattedStr(LocalDateTime localDateTime) {
    return DATE_TIME_FORMATTER.format(localDateTime);
}

private static LocalDateTime parseLocalDateTime(String formattedStr) {
    return LocalDateTime.parse(formattedStr, DATE_TIME_FORMATTER);
}

测试用例如下:

public class Application {
    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    public static void main(String[] args) {
        String formattedStr = getFormattedStr(LocalDateTime.now());
        System.out.println(formattedStr);
        LocalDateTime localDateTime = parseLocalDateTime(formattedStr);
        System.out.println(localDateTime);
    }

    private static String getFormattedStr(LocalDateTime localDateTime) {
        return DATE_TIME_FORMATTER.format(localDateTime);
    }

    private static LocalDateTime parseLocalDateTime(String formattedStr) {
        return LocalDateTime.parse(formattedStr, DATE_TIME_FORMATTER);
    }
}

测试用例输出结果如下所示:

2024-07-30 21:36:20
2024-07-30T21:36:20

2.Jackson与LocalDatetime

引入pom依赖

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

jackson-datatype-jsr310在原有Jackson基础上添加了对jsr310的支持, 即提供了序列化和反序列化LocalDateTime/LocalDate/LocalTime的能力,由于使用方式和原理相同,本文以LocalDateTime为例进行介绍。
在这里插入图片描述
测试用例:

@Slf4j
public class JacksonTest {
    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    @Test
    @SneakyThrows
    public void testJackson() {
        ObjectMapper objectMapper = getObjectMapper();
        Account account = new Account();
        account.setId(1).setName("name").setAddress("address").setMoney(100).setCtime(LocalDateTime.now()).setSex(Sex.FeMale);
        String str = objectMapper.writeValueAsString(account);

        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("str is {}.", str);
        }

        Account accountCopy = objectMapper.readValue(str,Account.class);
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("AccountCopy is {}.", accountCopy);
        }
    }

    public ObjectMapper getObjectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DATE_TIME_FORMATTER));
        javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DATE_TIME_FORMATTER));
        objectMapper.registerModule(javaTimeModule);
        return objectMapper;
    }
}

得到运行结果:
在这里插入图片描述
jackson-datatype-jsr310包中的JavaTimeModule类为ObjectMapper提供了序列化默认配置,这里只需要修改日期的序列化和反序列化时间格式即可。

3.Spring与LocalDatetime

Spring默认使用Jackson实现序列化和反序列的能力

SpringMVC处理客户端的HTTP请求时,会经过以下流程:
在这里插入图片描述
在进入业务处理逻辑(Controller层)前,SpringMVC框架会拦截请求🥷通过Convert将application/json格式的数据转化为Java对象;业务处理完成并响应数据时,通过Convert将java对象转换为application/json格式的字符串返回给客户端。Convert处理application/json数据与ava对象的过程中,就涉及序列化和反序列化问题。

首先,看一下案例:在Spring中可以通过注册Jackson2ObjectMapperBuilder这个Bean对象实现序列化配置;
引入pom依赖

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

另外,如果是SpringBoot项目,不需要额外引入该依赖:
在这里插入图片描述

@Bean
public Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder() {
    Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
    JavaTimeModule javaTimeModule = new JavaTimeModule();
    javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DATE_TIME_FORMATTER));
    javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DATE_TIME_FORMATTER));
    builder.modules(javaTimeModule);
    return builder;
}

上述Bean对象注入到IOC容器后,可以实现LocalDataTime系列(LocalDate)的序列化,这限制了整个SpringMVC使用LocalDateTime的格式,不利于扩展;可通过@JsonFormat注解针对不同的属性定制序列化和反序列化时的日期格式:

@Data
@Accessors(chain = true)
public class Account {
    private Integer id;

    private String name;

    private Integer money;

    private String address;

    private Sex sex;

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime ctime;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值