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

26 天前
 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 参数

2920 次点击
所在节点    程序员
46 条回复
baolinliu442k
26 天前
map
hidemyself
26 天前
@RequestBody Long taskId
这种写法,期望前端怎么传给你?
lisongeee
26 天前
呃,你没理解 JsonToken.START_OBJECT , 这错误不是很明显吗?

你的请求体不能是 {,你直接传 123 不就行了?
lovedoing
26 天前
RequestParam("taskId") 就行
lisongeee
26 天前
合法的 json 示例
{}
[]
123
"str"
null
true
flase
lychee930224
26 天前
userId 和 taskId 不能在一个对象里吗
dode
26 天前
PostMapping 也可以接收 RequestParam 参数
lovedoing
26 天前
不过需要前端把参数当 param 传,而不是 body
zerphyr
26 天前
既然定义了 Content-Type 为 json,那客户端和服务端都应该使用 json 格式,不存在其他方式
其次 json 格式有 ES6 解构,并不麻烦吧
myderr
26 天前
试试直接这样,如果是字符串类型,还得加双引号
carrotliang
26 天前
我理解你一个方法里接收的参数应该是确定的,新建一个 VO 对象,里面又有 userId 也有 taskId 。

如果不确定就用 Map 接收,get("taskId")
liumao
26 天前
map 一把梭
coollight56
26 天前
@myderr #10 谢谢 试了一下这样确实可以,但是我司前端一般不会这样传,都是 key value 的键值对,而且其中可能包含别的后端不要的键值对,可能用来做前端的某些判断逻辑,都一起传给后端了 T.T
vincentWdp
26 天前
首先, http 传输的内容全都是字节, 请求体的编码在 header content-encoding 里, 大概率是 utf-8, 有可能是 ascii, gbk... 等.
其次, 请求体的类型在 header content-type 里有写, 有的是 json, 有的是 stream, 有的是 form, 有的是 html...
再次, spring 框架肯定是符合 http 协议标准的, 如果你用 spring,就得和它一样遵守 http 协议标准.
最后, 再说你的疑惑, 如果前端不能改或者不想改, 你就和前端定好, 请求体用 application/json 类型, 然后后端用 map 接收.
zbw0414
26 天前
你这是查询请求(/info)吧, 如果是查询请求 应该用 @GetMapping, 请求参数放到 query_string 中,
前端发起请求类似 /info?taskId=123
后端 controller 类似
@GetMapping("/info")
public void info(@RequestParam Long taskId) {
System.out.println("taskId:" + taskId);
// TODO


}
zeww
26 天前
可以试试 @PathVariable
coollight56
26 天前
@carrotliang #11 谢谢 用 Map 确实可以解决,只不过可能还要转换不同参数的类型,如果能像 @RequestParam 一样在参数列表声明参数类型和参数名称,然后 spring web 自动转换那就更好,看来是只能自己封装了
coollight56
26 天前
@lisongeee #5 谢谢,涨知识了哈哈,确实可以直接传值,不过这里的场景请求方是用的 json 对象例如这样
{
"key1":"value1",
"key2":[],
"key3":1231
...
},所以我需要针对 json 对象做处理
leion8310
25 天前
要用 POST + JSON ,就老老实实把 taskId 封转在 Class 里,如

```java
public Class Task{
String taskId;
String taskName;
..
}
```

@RequestBody 注解只是帮你把实体对象反序列化成 JSON ,而不是帮你转类型...
niubilewodev
25 天前
这样 @RequestBody 就有歧义了。

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

https://yangjunhui.monster/t/1131110

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

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

© 2021 V2EX