比如 users/{user}/repos 这样的 path param, 对于 android 来说, 因为 retrofit 支持, 写起了体验很好, 所以 android 同事还是很喜欢的. 但是前端同事一般都比较抵触.
再比如只有一两个参数的 post 请求, 用 application/x-www-form-urlencoded ,客户端同事一般没啥意见. 但是前端一般会问能不能用 application/json 的.
还是挺有意思的. 哈哈
再比如只有一两个参数的 post 请求, 用 application/x-www-form-urlencoded ,客户端同事一般没啥意见. 但是前端一般会问能不能用 application/json 的.
指的不是后端的偏好.而是客户端的偏好.
换句话说, 客户端同事更倾向于择机使用 application/x-www-form-urlencoded 和 application/json, 复杂的用json, 简单的用form. 是混合使用的. 而前端同事更喜欢无脑json.
刚中午吃饭没事跟客户端闲聊了下, 他们表示少参数用form主要是为了避免创建没有意义的class. 比如
@FormUrlEncoded @POST("order/xxx") Call<ResponseBody> xxxxx(@Field("orderSn") String orderSn);
这种情况下如果要用json的话, 必须要建一个只有一个名为orderSn的field的class, 要么就是入参用map. 两者的可读性都不如 @Field("orderSn") String orderSn
so... 会向我们后端要求这个不用json而改成form
1 NathanDo 2021-12-17 11:27:39 +08:00 JSON 确实方便啊,直接定义对象就完了,application/x-www-form-urlencoded 的话得 ``` const body = new URLSearchParams(); body.append("customerNumber", "customerNumber"); body.append("password", "!password"); ``` 然后再 toString()一下 |
![]() | 2 66beta 2021-12-17 11:30:19 +08:00 ![]() json 更百搭,客户端同事偷懒罢了 XD |
4 daimubai 2021-12-17 11:34:51 +08:00 ![]() 这个和哪个端没关系。和对接的人有关系 |
5 yuningWang8 2021-12-17 11:35:33 +08:00 分人吧,作为前端,觉得第一种接口风格更好啊。 |
6 aikilan 2021-12-17 11:35:46 +08:00 其实无所谓,只要有约定的格式,多别扭都行,大不了前端封装个方法就是了。 |
![]() | 7 zoharSoul OP |
![]() | 8 marcong95 2021-12-17 11:58:14 +08:00 @daimubai #3 如果整套接口基本上基本是 x-www-form-urlencoded 的话,直接 axios 插个拦截器就好了把,不用 axios 那就自己封装个函数。那如果只是后端偷懒在几万个 json 的接口里塞了一两个 x-www-form-urlencoded ,这不抵触就有鬼了。。。 |
![]() | 9 IvanLi127 2021-12-17 12:12:19 +08:00 via Android 第二点的偏好是指客户端不介意不统一的接口返回而前端介意吗? |
![]() | 10 zoharSoul OP @marcong95 客户端同事喜欢混着, 而不是无脑 json. 比如只有几个字段的, 他们就不想让后端写成 json 的. 而喜欢用 form |
![]() | 11 dapang1221 2021-12-17 12:27:19 +08:00 go 后端:用 protobuf 吧 前端:? |
![]() | 12 zoharSoul OP ![]() @dapang1221 说道 protobuf, android 同事很喜欢这个, 据我了解. 似乎是因为 Google 官方对 protobuf 有支持, 只需要拿到 pb 文件, 就可以自动在 build 的时候生成全套请求, 只需要调用就行了, 比 golang 还方便. |
13 yikyo 2021-12-17 12:33:53 +08:00 via iPhone ![]() 前端只想统一,以前公司 post 数据时,一会 formdata ,一会 json ,真心烦 |
![]() | 14 chendy 2021-12-17 12:34:22 +08:00 可能是前端把 axios 配太死,只能发 application/json ,别的 content-type 都发不出来。。。 |
15 steptodream 2021-12-17 12:36:41 +08:00 我想知道一下,统一 json 的话,怎么在数据里带图片等文件参数,我是有文件的的请求就用 formdata ,没有就用 json |
![]() | 16 chairuosen 2021-12-17 12:37:24 +08:00 POST 有些后端还喜欢把一些参数放 query ,一些放 body |
17 knives 2021-12-17 12:38:29 +08:00 后端用 Spring MVC 的话,application/x-www-form-urlencoded 有一个好处,就是可以 Controller 中一个方法同时兼容 GET 和 POST 传参。application/json 的话要写实体和 @RequestBody 了。 |
18 Austaras 2021-12-17 13:01:40 +08:00 @steptodream base64 转一下,也不是不能用 |
![]() | 19 106npo 2021-12-17 13:03:54 +08:00 via Android 强类型语言用 JSON 得建实体类 。一个接口一个实体类谁受得了 |
![]() | 20 106npo 2021-12-17 13:05:41 +08:00 via Android 其实只要后端把 query 与 body 的 formData 和 json 合并了就皆大欢喜了 。 我们后端就是全兼容的 |
![]() | 22 yaphets666 2021-12-17 13:47:39 +08:00 原因就是 formData ,前端需要 let query = new FormData () 然后 append (‘a’,1 )。 json 只需要 let query={a:1} |
![]() | 23 yaphets666 2021-12-17 13:53:58 +08:00 还有 users/{user}/repos 这种东西。 前端一般是 在一个文件里把请求函数写好,再在组件中引用。 比如说在 api.js 里,定义好.例如 const req = data=> ajax('users/user/repos',data); 如果是这样的 users/{user}/repos 前端需要 const req = field=> ajax(users/${field}/repos);这显然有点奇怪 所以说不是个人好恶问题,而是实际开发的问题 |
![]() | 24 yaphets666 2021-12-17 13:57:11 +08:00 ![]() 总而言之,积极沟通,善待同事,对自己不懂的领域保持敬畏。 |
![]() | 25 icyalala 2021-12-17 13:58:32 +08:00 这其实是取决于各个端在实际开发中使用的网络请求下层封装是怎样的。 |
26 nikan999 2021-12-17 14:01:30 +08:00 不同语言对不同格式标准的支持复杂度不一样,两边都是希望往自己开发最简单的方向走的,没有什么问题 |
![]() | 27 yuuko 2021-12-17 14:08:33 +08:00 因为 JSON 相对客户端来说对前端更方便 |
![]() | 28 learningman 2021-12-17 14:11:09 +08:00 写个 builder 呗,都是写一次就能一直用的玩意儿( |
![]() | 29 Maboroshii 2021-12-17 14:11:09 +08:00 请问你这个是不同的项目吗,同一个项目为啥接口还有不同形式? |
![]() | 30 marcong95 2021-12-17 14:14:04 +08:00 @zoharSoul #10 实在是很简单的不想写实体类就用个 json 转 map 的解析库咯,一会 json 一会 x-www-form-urlencoded 太精分了吧。。。 |
![]() | 31 vanton 2021-12-17 14:17:12 +08:00 这个明显是客户端在偷懒了。 |
![]() | 33 imnpc 2021-12-17 14:31:34 +08:00 好像是前端 VUE 这种 上传文件麻烦 安卓客户端和 iOS 都是表单提交就过来了 |
34 fkdog 2021-12-17 14:49:25 +08:00 ![]() 最好的方就是扩展 spring , 同时 accept 接受 application/json 和 application/x-www-form-urlencoded 两种 request , 这样你们爱传啥传啥。 |
![]() | 36 johnnyNg 2021-12-17 15:28:13 +08:00 遇到过一次,接口结构定好了,同时开发,开发完了结果后端告诉我他那边全是 form 类型,当时就感觉日了狗了,我只能在我这边加了个拦截器,json 全部统一转成 form |
37 aguesuka 2021-12-17 16:07:52 +08:00 34 楼是对的, 虽然 spring 解决方案并不优雅 |
38 Leviathann 2021-12-17 16:09:39 +08:00 nominal type 就是这个麻烦,一定得定义一个 class/struct 出来 |
![]() | 39 Oktfolio 2021-12-17 16:23:10 +08:00 users/{user}/repos 这种 API ,我只在 Github 等这种国外产品见过。 工作中没有见过其他人用 POST GET DELETE 以外的方法,DELETE 都用得不多。PUT PATCH 没见过有人用。 json 和 fromdata ,能不用 formdata 就不用 formdata 。 只有 GET 使用 x-www-form-urlencoded 。 |
![]() | 40 erguotou521 2021-12-17 16:30:42 +08:00 via Android 代码生成治百病 |
41 preach 2021-12-17 16:34:55 +08:00 只要能用拦截器统一处理的都合理,取决于谁好说话 |
42 br_wang 2021-12-17 18:24:29 +08:00 post 请求搞 application/x-www-form-urlencoded 格式,涉及较复杂数据结构(对象、数组嵌套这种),我还真没遇到几个后端同学(语言是 python 、go )能正确取值处理,折腾半天都是后端同学先放弃,为了不耽误时间,还是 application/json 省时省力。 |
![]() | 43 zoharSoul OP @br_wang #42 不是说 application/x-www-form-urlencoded 和 application/json 谁好谁坏. 仅仅是分享下工作中发现的趣事, 即客户端同事更喜欢二者看场景来混合使用, 前端同事更喜欢无脑 json |
![]() | 44 zoharSoul OP @br_wang #42 比如你刚才提到的复杂场景, 很多 android 同学在这个时候就会要求用 json 的 |
![]() | 45 lesismal 2021-12-17 18:34:08 +08:00 妹妹你老公是真不行 |
46 Cbdy 2021-12-17 18:42:50 +08:00 via Android 作为一个前端,我喜欢无脑用 post ,无脑 post json ,这样就没有沟通成本了,post json 完事儿 |
47 Anarchy 2021-12-17 19:07:51 +08:00 via Android Android 用 retrofit 表单这种就直接定义接口的时候就写完了 |
48 geniusmary 2021-12-17 20:01:53 +08:00 鹅厂用的 pb 是真难受 |
49 kwanzaa 2021-12-17 20:30:52 +08:00 @dapang1221 客户端:好呀 |
50 dcsuibian 2021-12-17 21:24:09 +08:00 后端,无脑 json ,除非是文件上传。 看看大厂的公开 api 就知道了,json 更加通用,各种语言的支持也好。 而且 application/x-www-form-urlencoded 只是 http 协议里的吧? json 的应用场景更加广泛。spring-amqp 可以用 json ,数据库可以用 json……现在凡是涉及到跨语言通信的我都考虑 json ,甚至一般序列化也会用 json 。 |
51 dcsuibian 2021-12-17 21:31:17 +08:00 不过说起来(之前没怎么用过 application/x-www-form-urlencoded ),像是`@Field("orderSn") String orderSn`这个例子,没有 json 版的方案吗?比如`@JsonField("orderSn") String orderSn`这样的? |
![]() | 52 z42514 2021-12-17 21:35:14 +08:00 我 android 简单参数的时候,确实不喜欢用 json ,就是感觉建一个类好烦 |
![]() | 53 foam 2021-12-17 22:02:15 +08:00 其实是彼此都想着省事。POST payload 定一种数据协议就好了,这里明显是客户端同学偷懒了,根据代码写起来方便与否来决定用什么数据协议。 “少参数用 form 主要是为了避免创建没有意义的 class”,这类技术麻烦可以用技术手段解决,而不是要求外部改变接口的数据协议。 其实统一就好,不然还要仔细看 API 文档这是什么协议,也不方便维护。除非真的有什么特别的场景,再单独处理。 统一很重要。 |
![]() | 54 AV1 2021-12-17 22:23:25 +08:00 以前的项目,经常各种风格都有,包括 form 、xml 、json,甚至自立规范的 string 编码。 现在明白了,还是 json 最省事,不管是简单的一个 msg:ok ,还是复杂深层嵌套的数组和对象,都能胜任。 |
55 iseki 2021-12-17 22:28:17 +08:00 via Android 都想着省事,结果就是维护火葬场,大家一起费事~不如找好规范,折腾下 codegen ,麻烦一次后面就省事了 |
56 jinliming2 2021-12-17 22:34:12 +08:00 ![]() @NathanDo 你这是故意把代码写复杂了,如果使用原生的 fetch ,相比 application/json ,application/x-www-form-urlencoded 会更简单: ``` fetch'/', { method: 'POST', headers:{ 'content-type': 'application/json', }, body: JSON.stringify({ a: 1, b: 2, }), }) ``` 对比 ``` fetch('/', { method: 'POST', body: new URLSearchParams({ a: 1, b: 2, }), }) ``` 原因是浏览器默认网络请求都不认识 json 的,不指定 header 的话都默认 text/plain (如果 body 指定对象的话会自动 toString 变成 [object Object]),而 URLSearchParams 的构造函数就支持直接传对象,并且直接提交自动设置正确的请求头 application/x-www-form-urlencoded 。 @yaphets666 至于 FormData ,通常只会在上传文件的时候才会用(由于设计原因,平常用有点浪费网络资源,弱网环境影响体验)。而上传文件的话,你就要有个文件来源,一般是写一个 form 里带一个 input type="file",而 FormData 天生就为这个场景设计,只要 getElementById 拿到 form 对象,直接传给构造函数 new FormData(form) 就可以了。 同样代码也很简单,也会自动设置正确的请求头 multipart/form-data; boundary=xxx: ``` fetch('/', { method: 'POST', body: new FormData(document.getElementById('form')), }) ``` [当然,如果使用的是第三方的网络请求库的话,那应该是 JSON/x-www-form-urlencoded/form-data 站在同等地位啊,具体走什么都取决于封装而已。] |
57 jinliming2 2021-12-17 22:41:44 +08:00 @Austaras 图片用 base64 的话,文件体积会变大 1/3 ,并且代码量都比 FormData 要多了……还不如直接用 FormData 来的简单,并且用 FormData 只会固定大几个字节。 |
![]() | 58 jqtmviyu 2021-12-17 23:39:42 +08:00 喜欢无脑 json, 希望 post 都用 body 传参. 但后端说太麻烦要建实体类, 希望用 get 请求参数放在 query 和 params 里, 但真是别扭呀, 搜接口都不方便, 数据 query, params, body 都有, 乱乱的. |
![]() | 59 tagtag 2021-12-17 23:40:35 +08:00 什么都行,成套成标准就行,封装一下,用起来没有区别 |
![]() | 61 BigDogWang 2021-12-18 01:50:07 +08:00 作为客户端开发,一般所有的请求都要有一个对应的 request 类,不论什么数据格式全盘接受 |
62 siteshen 2021-12-18 02:11:31 +08:00 作为一个后端,我几乎都是选择 json ,不给前端和客户端任何选择的机会。 |
![]() | 63 pengtdyd 2021-12-18 02:44:46 +08:00 作为一个后端,是标准的制定者,其他人没资格谈条件! |
![]() | 64 passerbytiny 2021-12-18 07:04:06 +08:00 via Android 客户端是 Java Android 分支,前段是 Javascript **分支,后端接口的通信契约是 HTTP 协议、JSON 标准等,这本来就是相互独立的不同团体,不一样才是天为,一样了是才是人为。 |
![]() | 65 jobscolin 2021-12-18 09:18:36 +08:00 表示客户端从来没提过要求,后端要啥给啥。。。 |
![]() | 66 comoyi 2021-12-18 09:59:24 +08:00 作为后端一直要求接口使用方 POST 使用 application/x-www-form-urlencoded ,文件 form-data ,然后不管几个字段都定义结构体接收 |
![]() | 67 DDDZZZFFF 2021-12-18 15:47:14 +08:00 post,json 一把梭 |
![]() | 68 rosu 2021-12-18 19:23:25 +08:00 via iPhone 对于客户端来说,还是 Json 方便扩展,不然后续接口加参数,传参地方都得修改。 |
![]() | 69 abersheeran 2021-12-18 21:58:54 +08:00 我认识的很多菜鸟前端都分不清楚这几种提交格式的区别,所以我写的 web 框架的参数注入功能会自动判断,不管啥类型都能解析。反正实践里,前端很满意,后端也很满意。 |
70 Austaras 2021-12-19 00:24:41 +08:00 @jinliming2 没有啊,前端这边只需要封装个函数就完事了,乃至可以给 input 写个 directive 让它冒上来的就是 base64 |
![]() | 71 shayuvpn0001 2021-12-19 14:27:16 +08:00 @abersheeran 确实没啥区别啊,不都是字符串么 ![]() |
72 liuxue 2021-12-19 19:36:29 +08:00 个人前端, 很不喜欢 users/{user} 这样传递参数的方式。如果页面上多个接口都需要 user 这个参数,如果 user = 123456. 调试的时候就只能看到 123456.具体是哪个接口调用的查看起来不直观。 |
![]() | 73 risky 2021-12-19 21:51:51 +08:00 我们这里还可以 application/excel 直接返回文件下载 后端同学都感动哭了 |
![]() | 74 yaphets666 2021-12-20 09:11:00 +08:00 @jinliming2 请求肯定要统一定义的,不可能散乱的在各个组件中定义的,不然改起来好麻烦. |