JSON与表单POST的区别

48
我们正在讨论将数据发布到REST端点的问题。由于对象非常复杂,因此最简单的解决方案是将它们序列化为JSON格式并将其发送到请求正文中。
现在的问题是:这样做是否合适?或者应该将JSON设置为表单参数,例如data=[JSON]?或者将JSON发送到请求正文中是否仅仅是一种被弃用的方式,因为它强制客户端使用JavaScript来发送它们的数据,而不是让浏览器将数据打包为application/x-www-form-urlencoded
我知道这三个选项都可以“工作”,但哪个是“可取”的呢?或者至少推荐使用哪个?

4
我对这次讨论的结果很感兴趣,有什么最新消息吗?我目前的理解是,JSON内容应该作为POST数据的一部分传递,而任何可选参数仍然可以作为URL参数的一部分发送。这就是Twitter REST API的实现方法,只是作为参考。 - Soichi Hayashi
3个回答

29

我认为这两种方法都可以很好地工作,重要的是在API之间保持一致。我个人选择的选项是将内容作为application/json发送。

POST并不强制使用application/x-www-form-urlencoded——它只是因为Web浏览器使用它而经常使用。


3
为什么大多数网络浏览器使用 application/x-www-form-urlencoded 而不是 application/json?在我看来,application/json 更加灵活和表现力更强。 - stan25

7
直接将其作为序列化JSON发送没有任何问题,例如谷歌在其Volley库中默认这样做(这显然是他们为Android推荐的REST库)。
实际上,在SO上有很多关于如何不使用JSON而是使用Volley执行“正常”的POST请求的问题。 对于初学者来说,这有点违反直觉,因为必须重写基类的getParams()方法。
但是,谷歌拥有自己的REST库,并默认执行此操作,这表明这是可以的。

7
您可以将 JSON 作为请求数据的一部分,正如 OP 所说,这三个选项都适用。OP 需要支持 JSON 输入,因为它需要支持包含复杂结构内容的请求。但是,请这样想...您是在发出一个请求来执行某些操作,还是只发送基本的“文档”数据,并且恰巧使用 POST 操作作为创建新条目的等效方式。
既然如此,你所拥有的就是一个具有 CRUDL 语义的资源终端点。根据这一点,您实际上并不限于使用 application/json,而是可以使用资源终端点应该处理的任何类型。

对于非资源终端点

我发现(特别是对于 JAX-RS),application/x-www-urlencoded 更好。
  1. 与 OAuth 2.0 和 OpenID Connect 保持一致,它们使用 application/x-www-urlencoded
  2. 更容易使用 Swagger Annotations 注释每个字段
  3. Swagger 提供了更多默认值。
  4. Postman 为您生成了一个漂亮的表格,使测试变得更加容易。

非资源终端点的示例:

  • 认证
  • 授权
  • 简单搜索(尽管我会在此使用 GET
  • 非简单搜索,其中有许多条件
  • 发送消息/文档(尽管我也会考虑使用 multipart/form-data 以便可以在内容中传递元数据,但 JAX-RS 并没有对此进行标准化,Jersey 和 RestEasy 有自己的实现)

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