最后更新:2026-07-29
适用场景:Spring Boot 接收 JSON、@RequestBody、接收对象、接收数组、接收 List、接收 Map、接口联调、JSON 参数为空、415 Unsupported Media Type、JSON parse error
Spring Boot 写接口时,最常见的情况就是前端传一段 JSON,后端用 Java 对象接住。
看起来很简单:
@PostMapping("/users")
public String createUser(@RequestBody UserCreateRequest request) {
return "ok";
}
但实际开发里,这块经常出问题:
参数接收不到
@RequestBody 为空
Required request body is missing
415 Unsupported Media Type
JSON parse error
Cannot deserialize value of type
LocalDateTime 反序列化失败
前端传的是数组,后端用对象接
前端传的是 form-data,后端却用 @RequestBody 接
这篇就专门把 Spring Boot 接收 JSON 参数这件事讲清楚。
Spring MVC 中,@RequestBody 会把 HTTP 请求体交给 HttpMessageConverter 处理,再转换成控制器方法里声明的 Java 类型;如果是 JSON,一般就是由 Jackson 相关的消息转换器完成对象转换。官方文档也明确说明,@RequestBody 用于访问 HTTP request body,请求体内容会通过 HttpMessageConverter 转成方法参数类型。(Home)
一、先看结论
如果前端传的是 JSON,后端一般这样写:
@PostMapping("/users")
public String createUser(@RequestBody UserCreateRequest request) {
return "ok";
}
前端请求头必须是:
Content-Type: application/json
请求体示例:
{
"username": "zhangsan",
"age": 18
}
后端 DTO:
public class UserCreateRequest {
private String username;
private Integer age;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
如果用 Lombok,可以简化成:
import lombok.Data;
@Data
public class UserCreateRequest {
private String username;
private Integer age;
}
最容易踩坑的地方就三点:
1. 请求头不是 application/json
2. JSON 结构和 Java 接收类型不一致
3. 字段类型不匹配,比如字符串传给 Integer
二、接收普通 JSON 对象
这是最常见的情况。
前端传:
{
"username": "zhangsan",
"nickname": "张三",
"age": 18,
"enabled": true
}
后端 DTO:
import lombok.Data;
@Data
public class UserCreateRequest {
private String username;
private String nickname;
private Integer age;
private Boolean enabled;
}
Controller:
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/users")
public class UserController {
@PostMapping
public String createUser(@RequestBody UserCreateRequest request) {
System.out.println(request.getUsername());
System.out.println(request.getAge());
return "ok";
}
}
curl 测试:
curl -X POST http://localhost:8080/users \
-H "Content-Type: application/json" \
-d "{\"username\":\"zhangsan\",\"nickname\":\"张三\",\"age\":18,\"enabled\":true}"
注意:JSON 字段名和 Java 属性名要能对应上。
{
"username": "zhangsan"
}
对应:
private String username;
三、接收 JSON 数组
如果前端最外层传的是数组:
[
{
"username": "zhangsan",
"age": 18
},
{
"username": "lisi",
"age": 20
}
]
后端不能用普通对象接:
@RequestBody UserCreateRequest request
应该用 List:
@PostMapping("/batch")
public String batchCreate(@RequestBody List<UserCreateRequest> users) {
return "count: " + users.size();
}
完整示例:
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/users")
public class UserController {
@PostMapping("/batch")
public String batchCreate(@RequestBody List<UserCreateRequest> users) {
for (UserCreateRequest user : users) {
System.out.println(user.getUsername());
}
return "count: " + users.size();
}
}
记住一个简单规则:
JSON 最外层是 { },后端用对象接。
JSON 最外层是 [ ],后端用 List 接。
四、接收嵌套 JSON 对象
前端经常会传嵌套结构,比如用户信息里带地址:
{
"username": "zhangsan",
"address": {
"province": "浙江省",
"city": "杭州市",
"detail": "西湖区某某路"
}
}
后端 DTO 可以这样写:
import lombok.Data;
@Data
public class UserCreateRequest {
private String username;
private AddressRequest address;
}
import lombok.Data;
@Data
public class AddressRequest {
private String province;
private String city;
private String detail;
}
Controller 不需要特殊处理:
@PostMapping("/users")
public String createUser(@RequestBody UserCreateRequest request) {
System.out.println(request.getUsername());
System.out.println(request.getAddress().getCity());
return "ok";
}
嵌套对象不要硬用 Map 接。能定义 DTO 就定义 DTO,后期维护更清楚。
五、接收对象数组嵌套
再复杂一点,比如用户下面有订单列表:
{
"username": "zhangsan",
"orders": [
{
"orderNo": "A001",
"amount": 99.90
},
{
"orderNo": "A002",
"amount": 199.00
}
]
}
DTO:
import lombok.Data;
import java.util.List;
@Data
public class UserCreateRequest {
private String username;
private List<OrderRequest> orders;
}
import lombok.Data;
import java.math.BigDecimal;
@Data
public class OrderRequest {
private String orderNo;
private BigDecimal amount;
}
这里金额建议用 BigDecimal,不要用 Double。
private BigDecimal amount;
不建议:
private Double amount;
金额字段用浮点数,后面做计算时容易遇到精度问题。
六、接收 Map
有些接口字段不固定,或者只是临时调试,可以用 Map。
@PostMapping("/raw")
public String raw(@RequestBody Map<String, Object> body) {
System.out.println(body);
return "ok";
}
前端传:
{
"username": "zhangsan",
"extra": {
"source": "web",
"level": "vip"
}
}
后端可以这样取:
Object username = body.get("username");
Object extra = body.get("extra");
但正式业务接口不建议长期用 Map<String, Object>。
原因很简单:
字段不清楚
类型不清楚
接口文档不直观
参数校验不方便
后期维护容易出问题
更推荐:
正式接口:用 DTO
临时调试:可以用 Map
字段完全动态:可以考虑 JsonNode
七、接收 JsonNode
如果 JSON 很复杂,但你只想取其中几个字段,可以用 Jackson 的 JsonNode。
import com.fasterxml.jackson.databind.JsonNode;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/json")
public class JsonController {
@PostMapping("/node")
public String node(@RequestBody JsonNode root) {
String username = root.get("username").asText();
String city = root.get("address").get("city").asText();
System.out.println(username);
System.out.println(city);
return "ok";
}
}
请求:
{
"username": "zhangsan",
"address": {
"city": "杭州"
}
}
JsonNode 适合:
第三方接口结构不稳定
只读取部分字段
临时排查 JSON 结构
不想一开始就定义完整 DTO
但项目内部接口还是建议用 DTO。
八、接收 LocalDateTime
时间字段是 JSON 接收参数里最容易出问题的地方之一。
前端传:
{
"username": "zhangsan",
"createdAt": "2026-07-29 10:30:00"
}
Java DTO:
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class UserCreateRequest {
private String username;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
private LocalDateTime createdAt;
}
如果不加格式化配置,可能会遇到:
JSON parse error
Cannot deserialize value of type java.time.LocalDateTime
这类问题通常不是 Controller 写错了,而是:
前端时间格式
Java字段类型
Jackson时间格式配置
三者没有对齐。
我的建议是:项目里统一一种时间格式,比如:
yyyy-MM-dd HH:mm:ss
不要一个接口传:
2026-07-29 10:30:00
另一个接口传:
2026/07/29 10:30:00
再另一个传:
2026-07-29T10:30:00
格式越乱,联调问题越多。
九、字段名不一致怎么办
前端传的是下划线:
{
"user_name": "zhangsan"
}
Java 里一般写驼峰:
private String userName;
这时可以用 @JsonProperty:
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
@Data
public class UserCreateRequest {
@JsonProperty("user_name")
private String userName;
}
如果项目里所有字段都用下划线,也可以做全局命名策略。但如果只是个别字段不一致,@JsonProperty 更直观。
十、加参数校验
接收 JSON 参数时,通常还要做校验。
DTO:
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Data
public class UserCreateRequest {
@NotBlank(message = "用户名不能为空")
private String username;
@NotNull(message = "年龄不能为空")
private Integer age;
}
Controller:
import jakarta.validation.Valid;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/users")
public class UserController {
@PostMapping
public String createUser(@Valid @RequestBody UserCreateRequest request) {
return "ok";
}
}
@RequestBody 可以和 @Valid 或 @Validated 一起使用。Spring MVC 官方文档说明,@RequestBody 配合 jakarta.validation.Valid 或 Spring 的 @Validated 会触发标准 Bean Validation,默认校验失败会产生 MethodArgumentNotValidException,并返回 400 响应。(Home)
Spring Boot 项目还需要引入校验依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
十一、@RequestBody 和 @RequestParam 怎么选
这个地方很多人容易混。
前端传 JSON
请求头:
Content-Type: application/json
请求体:
{
"username": "zhangsan",
"age": 18
}
后端用:
@PostMapping("/users")
public String createUser(@RequestBody UserCreateRequest request) {
return "ok";
}
前端传表单参数
请求头:
Content-Type: application/x-www-form-urlencoded
请求体:
username=zhangsan&age=18
后端用:
@PostMapping("/users/form")
public String createUserForm(@RequestParam String username,
@RequestParam Integer age) {
return "ok";
}
官方文档也提醒,表单数据应该用 @RequestParam 读取,而不是依赖 @RequestBody;因为在 Servlet API 中,请求参数访问会导致请求体被解析,请求体不一定能再次可靠读取。(Home)
简单记:
JSON 请求体:@RequestBody
URL 查询参数:@RequestParam
表单提交:@RequestParam
路径变量:@PathVariable
文件上传:MultipartFile / @RequestPart
十二、一个接口能写多个 @RequestBody 吗?
一般不要。
错误写法:
@PostMapping("/users")
public String createUser(@RequestBody UserCreateRequest user,
@RequestBody AddressRequest address) {
return "ok";
}
HTTP 请求体只有一份,不能像普通参数一样拆成多个 @RequestBody。
应该定义一个包装对象:
import lombok.Data;
@Data
public class UserWithAddressRequest {
private UserCreateRequest user;
private AddressRequest address;
}
JSON:
{
"user": {
"username": "zhangsan",
"age": 18
},
"address": {
"city": "杭州",
"detail": "西湖区某某路"
}
}
Controller:
@PostMapping("/users")
public String createUser(@RequestBody UserWithAddressRequest request) {
return "ok";
}
十三、上传文件同时传 JSON 怎么办
如果是文件上传,同时带 JSON,不建议继续用普通 @RequestBody。
这种一般是 multipart/form-data。
前端可以传:
file: 文件
meta: JSON字符串
后端用 @RequestPart:
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
@RestController
@RequestMapping("/files")
public class FileController {
@PostMapping("/upload")
public String upload(@RequestPart("file") MultipartFile file,
@RequestPart("meta") FileMetaRequest meta) {
System.out.println(file.getOriginalFilename());
System.out.println(meta.getTitle());
return "ok";
}
}
DTO:
import lombok.Data;
@Data
public class FileMetaRequest {
private String title;
private String category;
}
Spring MVC 官方文档在 multipart 场景中也给出类似说明:如果 multipart 的某个 part 想像 JSON 一样反序列化,可以使用 @RequestPart,它会通过 HttpMessageConverter 转换该 part 的内容。(Home)
十四、常见错误一:Required request body is missing
报错:
Required request body is missing
常见原因:
1. 请求没有 body
2. 前端没有传 JSON
3. 请求方法不对
4. Content-Type 不对
5. body 被网关或过滤器读掉了
6. 用 GET 请求传 body
检查:
Postman / Apifox 是否选择 raw + JSON
请求头是否是 Content-Type: application/json
请求体是否真的有内容
Controller 是否写了 @RequestBody
正确请求:
curl -X POST http://localhost:8080/users \
-H "Content-Type: application/json" \
-d "{\"username\":\"zhangsan\"}"
十五、常见错误二:415 Unsupported Media Type
报错:
415 Unsupported Media Type
一般是请求头和后端接收方式不匹配。
比如后端是:
@PostMapping("/users")
public String createUser(@RequestBody UserCreateRequest request) {
return "ok";
}
但前端传的是:
Content-Type: application/x-www-form-urlencoded
这就容易出问题。
如果你要用 @RequestBody 接 JSON,请求头应该是:
Content-Type: application/json
curl:
curl -X POST http://localhost:8080/users \
-H "Content-Type: application/json" \
-d "{\"username\":\"zhangsan\",\"age\":18}"
十六、常见错误三:JSON parse error
报错:
JSON parse error
这个范围很大,常见原因包括:
JSON 格式不合法
字段类型不匹配
时间格式不匹配
数组和对象搞反
字符串没加双引号
多了逗号
前端传了空字符串
比如 JSON 写错:
{
"username": "zhangsan",
"age": 18,
}
最后多了一个逗号,JSON 不合法。
正确:
{
"username": "zhangsan",
"age": 18
}
建议先把 JSON 放到工具里校验一下。你也可以用:
Json哥 - JSON 在线解析、格式化、校验与实体类转换工具
十七、常见错误四:Cannot deserialize value of type
报错示例:
Cannot deserialize value of type `java.lang.Integer` from String "abc"
一般意思是:
前端传的字段类型,和 Java 接收类型不匹配。
例如后端:
private Integer age;
前端却传:
{
"age": "abc"
}
这肯定转不了。
正确:
{
"age": 18
}
再比如后端用对象接:
@RequestBody UserCreateRequest request
前端却传数组:
[
{
"username": "zhangsan"
}
]
这也不匹配。
十八、常见错误五:对象里全是 null
接口没有报错,但 DTO 里的字段都是 null。
常见原因:
1. JSON 字段名和 Java 字段名不一致
2. 没有 getter / setter
3. Lombok 没生效
4. 前端传的是嵌套对象,后端用平铺字段接
5. 请求体实际不是 JSON
比如前端:
{
"user_name": "zhangsan"
}
后端:
private String userName;
如果没有配置命名策略,也没有 @JsonProperty,就可能接不到。
可以这样写:
@JsonProperty("user_name")
private String userName;
十九、DTO 不要直接用 Entity
有些项目喜欢这样写:
@PostMapping("/users")
public String createUser(@RequestBody UserEntity entity) {
return "ok";
}
不建议。
更推荐:
Request DTO:接收前端参数
Entity / DO:对应数据库表
Response VO:返回给前端
例如:
@Data
public class UserCreateRequest {
private String username;
private String nickname;
private Integer age;
}
Entity 可能有这些字段:
id
password
deleted
createdAt
updatedAt
createdBy
version
internalStatus
这些字段不一定应该让前端传。
所以接口入参用 DTO,会更安全、更清楚。
二十、推荐的接口写法
一个比较舒服的写法是:
import jakarta.validation.Valid;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/users")
public class UserController {
@PostMapping
public ApiResult<Long> createUser(@Valid @RequestBody UserCreateRequest request) {
// 这里调用 service 保存用户
return ApiResult.success(1001L);
}
}
DTO:
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Data
public class UserCreateRequest {
@NotBlank(message = "用户名不能为空")
private String username;
private String nickname;
@NotNull(message = "年龄不能为空")
private Integer age;
}
返回对象示例:
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class ApiResult<T> {
private Integer code;
private String message;
private T data;
public static <T> ApiResult<T> success(T data) {
return new ApiResult<>(200, "success", data);
}
}
二十一、排查清单
如果 Spring Boot 接收 JSON 参数有问题,按这个顺序查:
1. 请求方法是不是 POST / PUT / PATCH
2. 请求头是不是 Content-Type: application/json
3. 请求体里是否真的有 JSON
4. JSON 格式是否合法
5. 最外层是对象还是数组
6. Java 接收类型是否匹配
7. 字段名是否一致
8. 字段类型是否一致
9. DTO 是否有 getter / setter
10. Lombok 是否生效
11. LocalDateTime 是否配置格式
12. 是否误用了 @RequestParam
13. 是否需要 @RequestPart
14. 是否有全局异常处理吞掉了真实报错
15. 是否使用了正确的 Spring Boot 和 Jackson 依赖
二十二、常见问题 FAQ
1. @RequestBody 是干什么的?
@RequestBody 用来读取 HTTP 请求体,并把请求体内容转换成 Java 对象。Spring MVC 会通过 HttpMessageConverter 完成这个转换。(Home)
2. JSON 参数必须加 @RequestBody 吗?
如果你想从请求体中读取 JSON,一般要加。
public String create(@RequestBody UserCreateRequest request)
如果是 URL 查询参数或表单参数,一般用 @RequestParam。
3. @RequestBody 可以接收 GET 请求吗?
不建议这么做。
GET 请求通常用查询参数:
/users?id=1
后端用:
@GetMapping("/users")
public String getUser(@RequestParam Long id) {
return "ok";
}
JSON 请求体更适合 POST、PUT、PATCH。
4. 为什么前端传了 JSON,后端接不到?
优先检查:
Content-Type 是否是 application/json
JSON 格式是否合法
字段名是否一致
Controller 是否写了 @RequestBody
请求体是否真的发出去了
5. JSON 数组怎么接收?
用 List<T>:
@PostMapping("/batch")
public String batch(@RequestBody List<UserCreateRequest> users) {
return "ok";
}
6. 表单提交能用 @RequestBody 吗?
不建议。
表单参数用 @RequestParam 更合适。Spring 官方文档也提醒,form data 应该用 @RequestParam 读取,而不是依赖 @RequestBody。(Home)
7. 文件上传加 JSON 怎么接?
用 multipart/form-data,后端用 @RequestPart:
@PostMapping("/upload")
public String upload(@RequestPart("file") MultipartFile file,
@RequestPart("meta") FileMetaRequest meta) {
return "ok";
}
8. LocalDateTime 接收失败怎么办?
字段上加:
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
private LocalDateTime createdAt;
同时要求前端传统一格式:
{
"createdAt": "2026-07-29 10:30:00"
}
二十三、最后总结
Spring Boot 接收 JSON 参数,核心就是三件事:
请求头对不对
JSON结构对不对
Java接收类型对不对
最常见写法:
@PostMapping("/users")
public String createUser(@RequestBody UserCreateRequest request) {
return "ok";
}
请求头:
Content-Type: application/json
请求体:
{
"username": "zhangsan",
"age": 18
}
不要把所有参数都塞进 Map,也不要直接用 Entity 接收前端参数。
正式业务接口建议用 Request DTO,字段清楚,后期更好维护。
二十四、相关文章
JSON 转 Java 实体类:
Spring Boot DataSource 报错:
Spring Boot启动报错 Failed to configure a DataSource 解决办法
Spring Boot 与 JDK 兼容:
Spring Boot 2 升级 3:
Spring Boot 2升级到Spring Boot 3完整指南
Java 开发环境配置:
Json 工具:
Json哥 - JSON 在线解析、格式化、校验与实体类转换工具
更新记录
2026-07-29:
- 创建 Spring Boot 接收 JSON 参数教程
- 增加对象、数组、嵌套对象、List、Map、JsonNode 接收示例
- 增加 LocalDateTime、@JsonProperty、@Valid 参数校验示例
- 增加 @RequestBody、@RequestParam、@RequestPart 区别说明
- 增加 Required request body is missing、415、JSON parse error 排查
Spring Boot 接收 JSON 参数
https://java.li/archives/spring-boot-requestbody-json
评论