如何使用cURL发送JSON数据的POST请求?

3751

我使用Ubuntu并在其上安装了cURL。 我想用cURL测试我的Spring REST应用程序。 我已经在Java端编写了我的POST代码,但是我想用cURL进行测试。 我试图发布JSON数据。 示例数据如下:

{"value":"30","type":"Tip 3","targetModule":"Target 3","configurationGroup":null,"name":"Configuration Deneme 3","description":null,"identity":"Configuration Deneme 3","version":0,"systemId":3,"active":true}

我使用这个命令:

curl -i \
    -H "Accept: application/json" \
    -H "X-HTTP-Method-Override: PUT" \
    -X POST -d "value":"30","type":"Tip 3","targetModule":"Target 3","configurationGroup":null,"name":"Configuration Deneme 3","description":null,"identity":"Configuration Deneme 3","version":0,"systemId":3,"active":true \
    http://localhost:8080/xx/xxx/xxxx

它返回了这个错误:

HTTP/1.1 415 Unsupported Media Type
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=utf-8
Content-Length: 1051
Date: Wed, 24 Aug 2011 08:50:17 GMT

错误描述如下:

服务器拒绝此请求,因为该请求实体格式不受所请求方法支持的所请求资源支持。

Tomcat日志: "POST /ui/webapp/conf/clear HTTP/1.1" 415 1051

什么是正确的cURL命令格式?

这是我的Java端 PUT 代码(我已经测试了GET和DELETE并且它们可以工作):

@RequestMapping(method = RequestMethod.PUT)
public Configuration updateConfiguration(HttpServletResponse response, @RequestBody Configuration configuration) { //consider @Valid tag
    configuration.setName("PUT worked");
    //todo If error occurs response.sendError(HttpServletResponse.SC_NOT_FOUND);
    return configuration;
}

7
请查看此链接:https://dev59.com/IOo6XIcBkEYKwwoYNBhQ#16909986,了解Spring 3.2.0中的POST请求。 - AmirHd
14
这里有一篇不错的文章使用Curl进行RESTful微服务的即席测试,其中包含多个示例。 - upitau
顺便提一下,在将 JSON 数据发送到服务器之前最好进行压缩。在2023年,使用smart json是更好的选择。 - cwtuan
33个回答

5558

你需要将内容类型设置为 application/json。但是 -d(或者 --data)默认发送 Content-Type 为 application/x-www-form-urlencoded,对 Spring 不被接受。

查看 curl man page,我认为你可以使用 -H(或者 --header):

-H "Content-Type: application/json"

完整示例:

curl --header "Content-Type: application/json" \
  --request POST \
  --data '{"username":"xyz","password":"xyz"}' \
  http://localhost:3000/api/login

(-H--header 的缩写,-d--data 的缩写)

请注意,如果您使用了 -d 标志,则 -request POST 是可选的,因为 -d 标志意味着一个 POST 请求。


在Windows上,情况略有不同。请参阅评论线程。

375
对于Windows系统,单引号无法正常使用json格式,因此我最终选择了转义双引号。curl -X POST -H "Content-Type: application/json" -d "{ \"key1\": \"value1\" }" http://localhost:3000/api/method - hIpPy
54
在Windows下,我需要使用引号来转义另一组引号,格式如下:"{ """key1""": """value1""" }"。此外,这个答案也可能对您有用:https://dev59.com/VWMl5IYBdhLWcg3wingW。 - chodorowicz
4
我之前在使用POST请求时遇到了问题,但是通过将"Application/json"的首字母大写解决了它,所以如果你遇到415错误,请检查大小写。 - Ebsan
3
@Adam Tuttle为什么你的评论有这么多赞?在Ubuntu 14.04上使用curl时,你需要使用"Content-Type: application/json"而不仅仅是"application/json"。这浪费了我很多时间... - ostrokach
10
@ostrokach抱歉让您浪费了时间。当我发布这条信息时,该语法在我的OSX上运行良好(尚未重试)。我想这只是平台差异。我想那些点赞是那些得到帮助的人。 - Adam Tuttle
显示剩余22条评论

729

试着把你的数据放到一个文件中,比如说body.json,然后使用以下代码:

curl -H "Content-Type: application/json" --data @body.json http://localhost:8080/ui/webapp/conf

32
建议使用--data-binary选项而非--data。人们可能期望客户端按原样发送数据,但是--data会从输入中剥离CR和LF。 - h2stein
29
使用cUrl与内联json字符串似乎很麻烦。需要转义双引号字符。使用类似这样的文件会更好。 - Aritz
67
在文件名之前加上“@”字符很重要,否则它将无法正常工作。我刚刚因为这个问题浪费了20分钟时间... - Radu Murzea
5
这样你也可以在文件上运行JSON检查工具,以查看是否存在解析JSON时的错误。 - datashaman
11
在Windows系统中,你需要在文件名"@body.json"周围加上双引号。 - Stomf
显示剩余6条评论

154

在Windows环境下,将-d的值用单引号括起来并不可行,但是使用双引号就可以了。同时,需要在花括号内转义双引号。

也就是说,以下方式不能正常工作:

curl -i -X POST -H "Content-Type: application/json" -d '{"key":"val"}' http://localhost:8080/appname/path

但是以下方法有效:

curl -i -X POST -H "Content-Type: application/json" -d "{\"key\":\"val\"}" http://localhost:8080/appname/path

6
谢谢提醒 - 看起来您在JSON正文中缺少一个闭合的双引号。 - acanby
4
对于我在Windows上的情况,“双引号”不起作用,应该使用没有引号的方式。 - rodedo
4
如果您正在使用PowerShell,请参考此答案 - rsenna
1
为了改善引号处理等问题,以及许多其他原因,请停止使用古老/弱 cmd.exe,并尝试使用改进的 shell 之一,例如来自 https://gitforwindows.org/ 网站的 Git-Bash。(即使您不使用 Git,也强烈推荐使用。) - MarkHu
是的,在 pwsh 中,引用行为是一种混乱的现象。但在 pwsh 7.3 中应该会得到修复,在 7.2 中,您可以运行 Enable-ExperimentalFeature PSNativeCommandArgumentPassing 来避免必须转义这些引号。 - Mariusz Pawelski

120

你可能会发现 resty 很有用:

它是 CURL 的包装器,简化了命令行 REST 请求。你将其指向你的 API 端点,就可以得到 PUT 和 POST 命令(示例改编自主页)。

resty http://127.0.0.1:8080/data #Sets up resty to point at your endpoing
GET /blogs.json                  #Gets http://127.0.0.1:8080/data/blogs.json
                                 #Put JSON
PUT /blogs/2.json '{"id" : 2, "title" : "updated post", "body" : "This is the new."}'
                                 # POST JSON from a file
POST /blogs/5.json < /tmp/blog.json

此外,通常仍然需要添加Content Type头信息。 您可以执行一次此操作以设置默认值,或根据方法和站点添加配置文件:设置默认RESTY选项


110

我使用以下方法解决了这个问题:

curl -H "Accept: application/json" -H "Content-type: application/json" -X POST -d '{"id":100}' http://localhost/api/postJsonReader.do

它被愉快地映射到Spring的控制器:

@RequestMapping(value = "/postJsonReader", method = RequestMethod.POST)
public @ResponseBody String processPostJsonData(@RequestBody IdOnly idOnly) throws Exception {
        logger.debug("JsonReaderController hit! Reading JSON data!"+idOnly.getId());
        return "JSON Received";
}

IdOnly是一个简单的POJO,它只有一个id属性。


80
您可以使用Postman将其转换为CURL命令:

这里输入图片描述

这里输入图片描述

注意:

最新版的Postman已进行了一些UI升级,现在代码链接位于侧边栏中。

这里输入图片描述


最佳答案,节省了很多时间,谢谢 :) - Amit Meena
这是一个不错的方法,让初学者了解从 UI 工具到 curl 命令的映射,但长期来看并不可持续,因为需要学习和维护另一个依赖项。 - Filip Seman

65
作为示例,创建一个JSON文件params.json,并将以下内容添加到其中:
[
    {
        "environment": "Devel",
        "description": "Machine for test, please do not delete!"
    }
]

然后你运行这个命令:

curl -v -H "Content-Type: application/json" -X POST --data @params.json -u your_username:your_password http://localhost:8000/env/add_server

专业提示:将以下行添加到您的~/.curlrc文件中:--header Content-Type:Application/JSON - MarkHu

50

我遇到了同样的问题。我通过指定解决了它。

-H "Content-Type: application/json; charset=UTF-8"

45

这对我非常有效。

curl -X POST --data @json_out.txt http://localhost:8080/

其中,

-X 表示 HTTP 请求方法。

--data 表示要发送的数据。


11
这个例子中的“-X POST”是多余的。 - Software Engineer
3
@软件工程师,但至少对于初学者来说是有指导意义的。 - Felipe Pereira
4
最好拥有透明但冗余的代码,而不是非透明的代码。我也更喜欢 --data 而不是 -d。这取决于团队整体在 Bash 方面的熟练程度,但对于 Bash 初学者和不经常使用它的人来说肯定更容易。 - Vadorequest

40

您可以使用具有直观GUI的Postman来组装cURL命令。

  1. 安装并启动Postman
  2. 输入您的URL、Post Body、请求头等等
  3. 点击Code
  4. 从下拉列表中选择cURL
  5. 复制并粘贴您的cURL命令

注意:下拉列表中有几个自动生成请求的选项,这也是我认为我的帖子很必要的原因。


9
没想到 Postman 已经包含了这个功能。谢谢你指出来! - ariestav

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接