Spring Boot Post请求无法接收JSON请求体中的DateTime参数
解决Spring Boot Post请求中DateTime类型参数的反序列化问题
问题根源
你遇到的400错误是因为Gson默认会将Joda-Time的DateTime类型解析为对象,但请求体中传递的是字符串格式的日期,导致反序列化时抛出Expected BEGIN_OBJECT but was STRING异常。同时你使用的是Jackson的@JsonFormat、@JsonDeserialize注解,这些注解在Gson作为JSON处理器时不会生效。
解决方案
方案一:自定义Gson的DateTime类型适配器
如果项目需要继续使用Gson,需要为DateTime类型自定义反序列化逻辑:
- 创建Gson TypeAdapter处理字符串转DateTime
import com.google.gson.TypeAdapter; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonWriter; import org.joda.time.DateTime; import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormatter; import java.io.IOException; public class DateTimeTypeAdapter extends TypeAdapter<DateTime> { // 匹配请求体的日期格式,指定UTC时区 private static final DateTimeFormatter FORMATTER = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").withZoneUTC(); @Override public void write(JsonWriter out, DateTime value) throws IOException { out.value(value == null ? null : FORMATTER.print(value)); } @Override public DateTime read(JsonReader in) throws IOException { String dateStr = in.nextString(); return dateStr == null || dateStr.isEmpty() ? null : FORMATTER.parseDateTime(dateStr); } }
- 配置Spring Boot使用自定义Gson实例
import com.google.gson.Gson; import com.google.gson.GsonBuilder; import org.joda.time.DateTime; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.json.GsonHttpMessageConverter; @Configuration public class GsonConfig { @Bean public GsonHttpMessageConverter gsonHttpMessageConverter() { GsonHttpMessageConverter converter = new GsonHttpMessageConverter(); Gson gson = new GsonBuilder() .registerTypeAdapter(DateTime.class, new DateTimeTypeAdapter()) .create(); converter.setGson(gson); return converter; } }
方案二:切换回Jackson(Spring Boot默认处理器)
如果没有强制使用Gson的需求,推荐使用Spring Boot默认的Jackson处理器,步骤如下:
- 添加Jackson处理Joda-Time的依赖(Maven)
<dependency> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-joda</artifactId> </dependency>
- 修正DTO类的注解
移除无效的@DateTimeFormat(该注解用于表单参数,不适用JSON请求体),使用Jackson的Joda-Time专用反序列化器:
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.datatype.joda.deser.DateTimeDeserializer; import org.joda.time.DateTime; import java.io.Serializable; public class FilteredJobsDto implements Serializable { private String jobName; private Long createdBy; private String status = "submitted"; private String tenantId; @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", timezone = "UTC") @JsonDeserialize(using = DateTimeDeserializer.class) private DateTime startDate; @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", timezone = "UTC") private DateTime endDate; // Getter、Setter 方法 }
- 确保项目未强制使用Gson
检查application.properties或application.yml,移除如下配置(如果存在):
spring.http.converter.preferred-json-mapper=gson
验证
修改完成后,用原请求体测试接口,即可正常解析startDate参数。
内容的提问来源于stack exchange,提问作者Sahil Ranjan
相关产品推荐
相关产品推荐

