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

MongoDB+SpringBoot兼容两种createdOn存储格式的解决方案

解决方案:兼容MongoDB中两种格式的createdOn字段转换

针对数据库中createdOn字段同时存在日期字符串(yyyy-dd-MM HH:mm:ssZ)和时间戳(epoch)两种格式,导致Spring/Mongo驱动转换Date类型失败的问题,提供以下两种优雅的兼容方案:

方案一:自定义MongoDB读取转换器(推荐)

通过注册MongoDB的自定义读取转换器,覆盖默认的类型转换逻辑,直接处理从MongoDB读取的各种类型的日期值。

1. 实现自定义转换器

创建@ReadingConverter注解的转换器,处理Object到Date的转换,兼容多种输入类型:

import org.springframework.core.convert.converter.Converter;
import org.springframework.data.convert.ReadingConverter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

@ReadingConverter
public class ObjectToDateConverter implements Converter<Object, Date> {
    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-dd-MM HH:mm:ssZ");

    @Override
    public Date convert(Object source) {
        if (source == null) {
            return null;
        }
        // 处理Mongo原生Date类型
        if (source instanceof Date) {
            return (Date) source;
        }
        // 处理字符串格式日期
        if (source instanceof String) {
            try {
                return DATE_FORMAT.parse((String) source);
            } catch (ParseException e) {
                // 兼容时间戳字符串(如数据库中直接存的数字字符串)
                try {
                    return new Date(Long.parseLong((String) source));
                } catch (NumberFormatException ex) {
                    throw new IllegalArgumentException("无法解析日期字符串: " + source, ex);
                }
            }
        }
        // 处理数字类型(Double/Long,对应$numberLong转换后的值)
        if (source instanceof Number) {
            long timestamp = ((Number) source).longValue();
            return new Date(timestamp);
        }
        throw new IllegalArgumentException("不支持的日期输入类型: " + source.getClass().getName());
    }
}

2. 注册转换器到Mongo配置

通过配置类将自定义转换器注入MongoTemplate:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.core.convert.MongoCustomConversions;
import java.util.Arrays;

@Configuration
public class MongoConfig {
    @Bean
    public MongoCustomConversions mongoCustomConversions() {
        return new MongoCustomConversions(Arrays.asList(new ObjectToDateConverter()));
    }
}

方案二:自定义Jackson反序列化器

通过自定义Jackson反序列化器,在Jackson绑定阶段处理多种格式的日期输入。

1. 实现多格式反序列化器

创建支持字符串、数字类型输入的反序列化器:

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class MultiFormatDateDeserializer extends JsonDeserializer<Date> {
    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-dd-MM HH:mm:ssZ");

    @Override
    public Date deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        Object currentValue = p.getCurrentValue();
        // 处理Mongo驱动转换后的数字类型(Double/Long)
        if (currentValue instanceof Number) {
            return new Date(((Number) currentValue).longValue());
        }
        // 处理字符串类型
        String strValue = p.getText().trim();
        try {
            return DATE_FORMAT.parse(strValue);
        } catch (ParseException e) {
            try {
                return new Date(Long.parseLong(strValue));
            } catch (NumberFormatException ex) {
                throw new IOException("无法解析日期值: " + strValue, ex);
            }
        }
    }
}

2. 绑定到实体类字段

在BaseModel的createdOn字段上添加@JsonDeserialize注解:

@Data
public class BaseModel {
    @Id
    @JsonSerialize(using= ObjectIdSerializer.class)
    protected ObjectId _id;
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-dd-MM HH:mm:ssZ")
    @JsonProperty("createdAt")
    @JsonDeserialize(using = MultiFormatDateDeserializer.class)
    Date createdOn;
}

说明

  • 方案一直接作用于MongoDB数据读取阶段,覆盖驱动默认转换逻辑,适配性更强;
  • 方案二作用于Jackson序列化/反序列化阶段,适合需要同时处理API请求和MongoDB数据的场景;
  • 两种方案均无需修改实体类的Date类型,也无需修复数据库数据,符合限制条件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 17:42:45