LocalDateTime序列化

记录springboot 项目 中LocalDateTime序列化失效问题的解决方案:

1、遇到的问题

比如下面的配置:

spring:
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
    # 默认策略,任何情况都执行序列化
    default-property-inclusion: always

但是使用 JsonFormat并未达到我想要的效果

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date endTime;

由于项目部署地和开发地不是同一个时区, 测试的时候发现页面显示的时间和数据库不一致,即:我们在哪里部署,当地的数据库和页面就保持一致。所以,不能直接设置时区(根据当前部署的OS自动设置)

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",locale = "zh", timezone = "GMT+8")
    private Date endTime;

2、解决方案

2.1 出参序列化

定义注解 LocalDateTimeFormat

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonSerialize(using = LocalDateTimeFormatSerialize.class)
public @interface LocalDateTimeFormat {
    String pattern() ;
}

定义序列化类

import cn.hutool.core.date.LocalDateTimeUtil;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import java.io.IOException;
import java.util.Date;
import java.util.Objects;
/**
 * @author : qinjinyuan
 * @desc : localDateTime format
 * @date : 2023/12/06 20:08
 */
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class LocalDateTimeFormatSerialize extends JsonSerializer implements ContextualSerializer {

    private String pattern;

    @Override
    public void serialize(Object objValue, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        if (Objects.isNull(objValue)) {
            jsonGenerator.writeString("");
            return;
        }
        Date value = (Date) objValue;
        jsonGenerator.writeString(LocalDateTimeUtil.format(LocalDateTimeUtil.of(value), pattern));
    }

    @Override
    public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) throws JsonMappingException {
        if (Objects.nonNull(beanProperty)) {
            if (Objects.equals(beanProperty.getType().getRawClass(), Date.class)) {
                LocalDateTimeFormat anno = beanProperty.getAnnotation(LocalDateTimeFormat.class);
                if (Objects.isNull(anno)) {
                    anno = beanProperty.getContextAnnotation(LocalDateTimeFormat.class);
                }
                if (Objects.nonNull(anno)) {
                    this.pattern = anno.pattern();
                    return new LocalDateTimeFormatSerialize(pattern);
                }
            }
            return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);
        }
        return serializerProvider.findNullValueSerializer(null);
    }
}

DTO中使用栗子

    @LocalDateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @ApiModelProperty(value = "创建时间")
    private Date createTime;

2.2 入参反序列化Deserializer

定义类CustomerDateDeserializer (字符串 -> LocalDateTime)

package com.sikaryofficial.common.core.annotation;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.text.CharSequenceUtil;
import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.jackson.JsonComponent;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.Date;

/**
 * @author : qinjinyuan
 * @desc : 自定义反序列化器,格式化时间
 * @date : 2023/12/14 9:53
 */
@Slf4j
@JsonComponent
public class CustomerDateDeserializer extends JsonDeserializer<Date> {
    /**
     * @param jsonParser
     * @param deserializationContext
     * @return
     * @throws IOException
     * @throws JacksonException
     */
    @Override
    public Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
        if(CharSequenceUtil.isBlank(jsonParser.getText())){
            return null;
        }
        LocalDateTime localDateTime = LocalDateTimeUtil.parse(jsonParser.getText(), "yyyy-MM-dd HH:mm:ss");
        return new DateTime(localDateTime);
    }
}

request 中使用栗子

    @ApiModelProperty(value = "开始日期", example = "yyyy-MM-dd HH:mm:ss")
    @JsonDeserialize(using = CustomerDateDeserializer.class)
    private Date startTime;
    @ApiModelProperty(value = "结束时间", example = "yyyy-MM-dd HH:mm:ss")
    @JsonDeserialize(using = CustomerDateDeserializer.class)
    private Date endTime;

3、小结

LocalDateTime 是JDK8推出, 时区是根据操作系统来进行设置,方便我们使用跟时区有关系的时间; spring 内置 Jackson, 如果通过配置无法解决类似问题,可以采用我的方案。

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值