关于 Java spring web 接收 Content-Type=application/json 请求参数的问题

2025 年 5 月 12 日
 coollight56

请问 spring web 只能用 @RequestBody 来接受 json 格式参数吗? 而且好像必须是用对象来接收

比如下面的情况就会报错 json 参数为

{
    "taskId":123
    ....
}

controller 为

    @PostMapping("/info")
    public void info(@RequestBody Long taskId) {
		System.out.println("taskId:" + taskId);
		// TODO
        
        
    }

错误提示

Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type `java.lang.Long` from Object value (token `JsonToken.START_OBJECT`)]

但是只要把 taskId 包装到一个对象中就可以正常接收,然而这样会不会太麻烦了,例如我又要接收一个 userId 那又得创建一个对象,spring web 不考虑自己封装的情况下(因为感觉这种场景应该很多才对,可能是我没掌握)有什么办法可以像 @RequestParam (只要定义需要接受的参数类型和名称就可以)来接收 json 参数

4839 次点击
所在节点    程序员
46 条回复
xiaohupro
2025 年 5 月 12 日
最好定义一个对应的参数类,例如:xxxParam.java ,一般项目中我就会这样定义,方便后期维护,而且这样定义了之后 post 和 get 都能用
ZeroDu
2025 年 5 月 12 日
spring 的做法是正确的。op 缺少一些理解。
Kaiv2
2025 年 5 月 12 日
不推荐使用 Map ,定义一个对象,有 lombok 和 AI 定义一个对象花不了多少时间。代码更安全也更好维护。
bitmin
2025 年 5 月 12 日
a = {
"taskId":123
....
}

request body 是 a 而不是 taskId

你想直接取 taskId 看看 @RequestBody 有没有参数设置,类似 python fastapi 里 task_id: int = Body(..., embed=True) 指定 embed=True

@RequestBody 没有这样的功能可以自己自定义一个注解例如 @EmbedRequestBody ,如果用了文档生成的库或者插件,可能会不识别自定义的注解,还得去做兼容
NickX
2025 年 5 月 12 日
@RequestBody 就是用来接收 application/json 的类型,你非得让他接收表单,明显是用法问题。用 @RequestParam 吧
hailiang88
2025 年 5 月 12 日
把 post 改成 get ,参数使用 @PathValue 的格式或许更符合 rest 规范吧
coollight56
2025 年 5 月 12 日
@bitmin #24 是的 看了下别的人的处理方法都是自定义一个注解 ,文档生成确实就没法兼容了
https://blog.csdn.net/llwutong/article/details/116273360
ikas
2025 年 5 月 12 日
创建一个专门用于接收 Id 的参数类型算了.
record IdParam<T>(T id){}
ikas
2025 年 5 月 12 日
我们是统一了前端传递的参数名
coollight56
2025 年 5 月 12 日
@ikas #29 嗯嗯 这也是一种方法 👍
xuanbg
2025 年 5 月 12 日
你要是觉得定义一个对象很麻烦,那也可以用万能的 Map 来接收的。只是 key 改了名字就比较麻烦。
itechify
2025 年 5 月 12 日
OP 刚刚入行? content type 的含义就是客户端和服务端数据交互的格式定义协议。json 代表客户端按照 json 格式传参,相对的,服务端就得按照 json 格式解析
Hstar
2025 年 5 月 12 日
楼主脑洞有点大, 经验有点少. 建议你听大家的, 就把 taskId 封在一个 Class 里.
然后你记得收藏一下这个帖子, 等五年十年后你再回来看自己的发言和思路, 有惊喜!
iv8d
2025 年 5 月 12 日
你直接写数字到 data 就行了
cenbiq
2025 年 5 月 13 日
看了半天也没看懂 OP 的问题在哪,我想几乎所有语言/框架对 POST 请求的处理都是类似 fun info(queryParam1: Int, queryParam2: String?, body: InfoRequestBodyJsonMappingObject): InfoResponseContentJsonMappingObject 这种形式吧,应该不存在任何疑问?
cenbiq
2025 年 5 月 13 日
@cenbiq 依据 OP 的需求 InfoRequestBodyJsonMappingObject(taskId: Long, taskName: String, userId: Long) 这样存在任何疑问吗
cenbiq
2025 年 5 月 13 日
@cenbiq 如果你的框架支持,应该还能这么做 fun info(task: TaskPartOfInfoBodyObject, user: UserPartOfInfoBodyObject); 数据类型定义是 TaskPartOfInfoBodyObject(taskId: Long, taskName: String); UserPartOfInfoBodyObject(userId: Long, ...)。如果 OP 是想要从 body 的一个 json 内分出两组请求数据方便处理的话
shangfabao
2025 年 5 月 13 日
你要是按照参数方式获取,注解都不对啊,肯定取不到
coollight56
2025 年 5 月 13 日
@cenbiq #37 @cenbiq #36 是的 就是想要把单个 json 对象里的属性拆分开来在 controller 方法参数列表上接收,我这几天已经看到别的大佬的实现,就是自己写一个注解然后处理,spring web 也提供了这方面的扩展,同时也实现了组合参数的接收,如下
```java

public ApiResult<PageResult<?>> schemeUserList(@SingleParam @NotNull Long schemeId,
@ComboParam @Valid UserSearchParam userSearchParam,
@ComboParam @Valid PageParam pageParam) {
// TODO
}

```
这样真的很方便,不过大家讨论的更多是全部用 json 来传参符不符合规范。确实不知道怎么样才规范,好像都是学习前人的代码风格,然后想在此基础上优化而已。
coollight56
2025 年 5 月 13 日
@coollight56 #39 显示不友好 写到补充里了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://v2ex.ih06.com/t/1131110

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX