Flutter DateTime与Spring Boot LocalDateTime适配:忽略毫秒的处理方案咨询
解决Spring Boot接收可变毫秒位数LocalDateTime的问题
问题核心
客户端发送的时间字符串包含可变位数的毫秒(.SS/.SSS/.SSSS等),服务端需要将其解析为秒级精度的LocalDateTime,直接使用@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")会因格式不匹配抛出解析异常。
方案1:自定义字段级反序列化器
针对单个DTO字段定制解析逻辑,既兼容可变毫秒位数,又自动截断到秒级精度。
- 编写自定义反序列化器:
import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import java.io.IOException; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatterBuilder; import java.time.temporal.ChronoField; public class TruncatedLocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> { // 定义兼容1-9位毫秒/纳秒的格式化器 private static final DateTimeFormatter FORMATTER = new DateTimeFormatterBuilder() .appendPattern("yyyy-MM-dd HH:mm:ss") .optionalStart() .appendFraction(ChronoField.NANO_OF_SECOND, 1, 9, true) .optionalEnd() .toFormatter(); @Override public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { String dateStr = p.getText().trim(); LocalDateTime dateTime = LocalDateTime.parse(dateStr, FORMATTER); return dateTime.withNano(0); // 截断毫秒,保留秒级精度 } }
- 在DTO字段上应用该反序列化器:
public class YourRequestDTO { @JsonDeserialize(using = TruncatedLocalDateTimeDeserializer.class) private LocalDateTime targetDateTime; // Getter & Setter }
方案2:全局Jackson配置
如果需要所有LocalDateTime类型都采用相同的解析规则,可以全局配置Jackson:
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatterBuilder; import java.time.temporal.ChronoField; @Configuration public class JacksonGlobalConfig { @Bean public ObjectMapper objectMapper() { ObjectMapper objectMapper = new ObjectMapper(); JavaTimeModule timeModule = new JavaTimeModule(); DateTimeFormatter formatter = new DateTimeFormatterBuilder() .appendPattern("yyyy-MM-dd HH:mm:ss") .optionalStart() .appendFraction(ChronoField.NANO_OF_SECOND, 1, 9, true) .optionalEnd() .toFormatter(); // 替换默认反序列化器,添加截断毫秒逻辑 timeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(formatter) { @Override public LocalDateTime deserialize(com.fasterxml.jackson.core.JsonParser p, DeserializationContext ctxt) throws IOException { LocalDateTime dateTime = super.deserialize(p, ctxt); return dateTime.withNano(0); } }); objectMapper.registerModule(timeModule); return objectMapper; } }
方案3:简化版(依赖Setter截断)
如果不想编写自定义序列化器,也可以结合@JsonFormat的宽松模式+Setter手动截断:
public class YourRequestDTO { @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS", lenient = OptBoolean.TRUE) private LocalDateTime targetDateTime; public void setTargetDateTime(LocalDateTime targetDateTime) { this.targetDateTime = targetDateTime.withNano(0); // 手动截断毫秒 } // Getter }
注意:这种方式依赖Jackson的宽松解析规则,兼容性不如前两种方案,仅适合简单场景。
内容的提问来源于stack exchange,提问作者Demir
相关产品推荐
相关产品推荐

