V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
zoharSoul
V2EX  ›  程序员

发现客户端同学和前端的对于接口风格的偏好还是有些不一致的

  •  1
     
  •   zoharSoul · 158 天前 · 5666 次点击
    这是一个创建于 158 天前的主题,其中的信息可能已经有所发展或是发生改变。

    比如 users/{user}/repos 这样的 path param, 对于 android 来说, 因为 retrofit 支持, 写起了体验很好, 所以 android 同事还是很喜欢的. 但是前端同事一般都比较抵触.

    再比如只有一两个参数的 post 请求, 用 application/x-www-form-urlencoded ,客户端同事一般没啥意见. 但是前端一般会问能不能用 application/json 的.

    还是挺有意思的. 哈哈

    第 1 条附言  ·  158 天前

    再比如只有一两个参数的 post 请求, 用 application/x-www-form-urlencoded ,客户端同事一般没啥意见. 但是前端一般会问能不能用 application/json 的.

    指的不是后端的偏好.而是客户端的偏好.

    换句话说, 客户端同事更倾向于择机使用 application/x-www-form-urlencoded 和 application/json, 复杂的用json, 简单的用form. 是混合使用的. 而前端同事更喜欢无脑json.

    第 2 条附言  ·  157 天前

    刚中午吃饭没事跟客户端闲聊了下, 他们表示少参数用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

    第 3 条附言  ·  157 天前
    这里并非争论 application/x-www-form-urlencoded 和 application/json 谁好谁坏.

    仅仅是分享下工作中发现的趣事,
    即客户端同事更喜欢二者看场景来混合使用, 前端同事更喜欢无脑 json
    74 条回复    2021-12-20 09:11:00 +08:00
    NathanDo
        1
    NathanDo  
       158 天前
    JSON 确实方便啊,直接定义对象就完了,application/x-www-form-urlencoded 的话得
    ```
    const body = new URLSearchParams();
    body.append("customerNumber", "customerNumber");
    body.append("password", "!password");
    ```
    然后再 toString()一下
    66beta
        2
    66beta  
       158 天前   ❤️ 1
    json 更百搭,客户端同事偷懒罢了 XD
    daimubai
        3
    daimubai  
       158 天前
    @NathanDo json 当然方便,楼主说的是只有一两个参数的情况下,后端偷懒不想去建个实体
    daimubai
        4
    daimubai  
       158 天前   ❤️ 2
    这个和哪个端没关系。和对接的人有关系
    yuningWang8
        5
    yuningWang8  
       158 天前
    分人吧,作为前端,觉得第一种接口风格更好啊。
    aikilan
        6
    aikilan  
       158 天前
    其实无所谓,只要有约定的格式,多别扭都行,大不了前端封装个方法就是了。
    zoharSoul
        7
    zoharSoul  
    OP
       158 天前
    @NathanDo #1
    @daimubai #3

    再比如只有一两个参数的 post 请求, 用 application/x-www-form-urlencoded ,客户端同事一般没啥意见. 但是前端一般会问能不能用 application/json 的.

    这种情况下客户端同事更喜欢 application/x-www-form-urlencoded 的, 而不是 json. 指的不是后端的偏好.而是客户端的偏好
    marcong95
        8
    marcong95  
       158 天前
    @daimubai #3 如果整套接口基本上基本是 x-www-form-urlencoded 的话,直接 axios 插个拦截器就好了把,不用 axios 那就自己封装个函数。那如果只是后端偷懒在几万个 json 的接口里塞了一两个 x-www-form-urlencoded ,这不抵触就有鬼了。。。
    IvanLi127
        9
    IvanLi127  
       158 天前 via Android
    第二点的偏好是指客户端不介意不统一的接口返回而前端介意吗? 😏
    zoharSoul
        10
    zoharSoul  
    OP
       158 天前
    @marcong95 客户端同事喜欢混着, 而不是无脑 json. 比如只有几个字段的, 他们就不想让后端写成 json 的. 而喜欢用 form
    dapang1221
        11
    dapang1221  
       158 天前
    go 后端:用 protobuf 吧
    前端:?
    zoharSoul
        12
    zoharSoul  
    OP
       158 天前   ❤️ 1
    @dapang1221 说道 protobuf, android 同事很喜欢这个, 据我了解. 似乎是因为 Google 官方对 protobuf 有支持, 只需要拿到 pb 文件, 就可以自动在 build 的时候生成全套请求, 只需要调用就行了, 比 golang 还方便.
    yikyo
        13
    yikyo  
       158 天前 via iPhone   ❤️ 1
    前端只想统一,以前公司 post 数据时,一会 formdata ,一会 json ,真心烦
    chendy
        14
    chendy  
       158 天前
    可能是前端把 axios 配太死,只能发 application/json ,别的 content-type 都发不出来。。。
    steptodream
        15
    steptodream  
       158 天前
    我想知道一下,统一 json 的话,怎么在数据里带图片等文件参数,我是有文件的的请求就用 formdata ,没有就用 json
    chairuosen
        16
    chairuosen  
       158 天前
    POST 有些后端还喜欢把一些参数放 query ,一些放 body
    knives
        17
    knives  
       158 天前
    后端用 Spring MVC 的话,application/x-www-form-urlencoded 有一个好处,就是可以 Controller 中一个方法同时兼容 GET 和 POST 传参。application/json 的话要写实体和 @RequestBody 了。
    Austaras
        18
    Austaras  
       158 天前
    @steptodream base64 转一下,也不是不能用
    xmumiffy
        19
    xmumiffy  
       158 天前 via Android
    强类型语言用 JSON 得建实体类 。一个接口一个实体类谁受得了
    xmumiffy
        20
    xmumiffy  
       158 天前 via Android
    其实只要后端把 query 与 body 的 formData 和 json 合并了就皆大欢喜了 。
    我们后端就是全兼容的
    wu67
        21
    wu67  
       157 天前
    @xmumiffy >> 一个接口一个实体类谁受得了

    有些前端甚至恨不得所有数据都用 ts 写上类型结构啥的呢...
    yaphets666
        22
    yaphets666  
       157 天前
    原因就是 formData ,前端需要 let query = new FormData () 然后 append (‘a’,1 )。
    json 只需要 let query={a:1}
    yaphets666
        23
    yaphets666  
       157 天前
    还有 users/{user}/repos 这种东西。 前端一般是 在一个文件里把请求函数写好,再在组件中引用。
    比如说在 api.js 里,定义好.例如 const req = data=> ajax('users/user/repos',data);
    如果是这样的 users/{user}/repos 前端需要 const req = field=> ajax(·users/${field}/repos·);这显然有点奇怪

    所以说不是个人好恶问题,而是实际开发的问题
    yaphets666
        24
    yaphets666  
       157 天前   ❤️ 1
    总而言之,积极沟通,善待同事,对自己不懂的领域保持敬畏。
    icyalala
        25
    icyalala  
       157 天前
    这其实是取决于各个端在实际开发中使用的网络请求下层封装是怎样的。
    nikan999
        26
    nikan999  
       157 天前
    不同语言对不同格式标准的支持复杂度不一样,两边都是希望往自己开发最简单的方向走的,没有什么问题
    yuuko
        27
    yuuko  
       157 天前
    因为 JSON 相对客户端来说对前端更方便
    learningman
        28
    learningman  
       157 天前
    写个 builder 呗,都是写一次就能一直用的玩意儿(
    Maboroshii
        29
    Maboroshii  
       157 天前
    请问你这个是不同的项目吗,同一个项目为啥接口还有不同形式?
    marcong95
        30
    marcong95  
       157 天前
    @zoharSoul #10 实在是很简单的不想写实体类就用个 json 转 map 的解析库咯,一会 json 一会 x-www-form-urlencoded 太精分了吧。。。
    vanton
        31
    vanton  
       157 天前
    这个明显是客户端在偷懒了。
    zoharSoul
        32
    zoharSoul  
    OP
       157 天前
    @marcong95 那要问客户端同学咋想的了. 反正要啥给啥 /狗头
    imnpc
        33
    imnpc  
       157 天前
    好像是前端 VUE 这种 上传文件麻烦
    安卓客户端和 iOS 都是表单提交就过来了
    fkdog
        34
    fkdog  
       157 天前   ❤️ 1
    最好的方法就是扩展 spring ,
    同时 accept 接受 application/json 和 application/x-www-form-urlencoded 两种 request ,
    这样你们爱传啥传啥。
    zoharSoul
        35
    zoharSoul  
    OP
       157 天前
    @vanton 为什么不是前端偷懒呢? /狗头
    johnnyNg
        36
    johnnyNg  
       157 天前
    遇到过一次,接口结构定好了,同时开发,开发完了结果后端告诉我他那边全是 form 类型,当时就感觉日了狗了,我只能在我这边加了个拦截器,json 全部统一转成 form
    aguesuka
        37
    aguesuka  
       157 天前
    34 楼是对的, 虽然 spring 解决方案并不优雅
    Leviathann
        38
    Leviathann  
       157 天前
    nominal type 就是这个麻烦,一定得定义一个 class/struct 出来
    Oktfolio
        39
    Oktfolio  
       157 天前
    users/{user}/repos 这种 API ,我只在 Github 等这种国外产品见过。

    工作中没有见过其他人用 POST GET DELETE 以外的方法,DELETE 都用得不多。PUT PATCH 没见过有人用。

    json 和 fromdata ,能不用 formdata 就不用 formdata 。

    只有 GET 使用 x-www-form-urlencoded 。
    erguotou521
        40
    erguotou521  
       157 天前 via Android
    代码生成治百病
    preach
        41
    preach  
       157 天前
    只要能用拦截器统一处理的都合理,取决于谁好说话
    br_wang
        42
    br_wang  
       157 天前
    post 请求搞 application/x-www-form-urlencoded 格式,涉及较复杂数据结构(对象、数组嵌套这种),我还真没遇到几个后端同学(语言是 python 、go )能正确取值处理,折腾半天都是后端同学先放弃,为了不耽误时间,还是 application/json 省时省力。
    zoharSoul
        43
    zoharSoul  
    OP
       157 天前
    @br_wang #42

    不是说 application/x-www-form-urlencoded 和 application/json 谁好谁坏.

    仅仅是分享下工作中发现的趣事,
    即客户端同事更喜欢二者看场景来混合使用, 前端同事更喜欢无脑 json
    zoharSoul
        44
    zoharSoul  
    OP
       157 天前
    @br_wang #42 比如你刚才提到的复杂场景, 很多 android 同学在这个时候就会要求用 json 的
    lesismal
        45
    lesismal  
       157 天前
    妹妹你老公是真不行
    Cbdy
        46
    Cbdy  
       157 天前 via Android
    作为一个前端,我喜欢无脑用 post ,无脑 post json ,这样就没有沟通成本了,post json 完事儿
    Anarchy
        47
    Anarchy  
       157 天前 via Android
    Android 用 retrofit 表单这种就直接定义接口的时候就写完了
    geniusmary
        48
    geniusmary  
       157 天前
    鹅厂用的 pb 是真难受
    kwanzaa
        49
    kwanzaa  
       157 天前
    @dapang1221 客户端:好呀
    dcsuibian
        50
    dcsuibian  
       157 天前
    后端,无脑 json ,除非是文件上传。
    看看大厂的公开 api 就知道了,json 更加通用,各种语言的支持也好。
    而且 application/x-www-form-urlencoded 只是 http 协议里的吧? json 的应用场景更加广泛。spring-amqp 可以用 json ,数据库可以用 json……现在凡是涉及到跨语言通信的我都考虑 json ,甚至一般序列化也会用 json 。
    dcsuibian
        51
    dcsuibian  
       157 天前
    不过说起来(之前没怎么用过 application/x-www-form-urlencoded ),像是`@Field("orderSn") String orderSn`这个例子,没有 json 版的方案吗?比如`@JsonField("orderSn") String orderSn`这样的?
    z42514
        52
    z42514  
       157 天前
    我 android 简单参数的时候,确实不喜欢用 json ,就是感觉建一个类好烦
    foam
        53
    foam  
       157 天前
    其实是彼此都想着省事。POST payload 定一种数据协议就好了,这里明显是客户端同学偷懒了,根据代码写起来方便与否来决定用什么数据协议。

    “少参数用 form 主要是为了避免创建没有意义的 class”,这类技术麻烦可以用技术手段解决,而不是要求外部改变接口的数据协议。

    其实统一就好,不然还要仔细看 API 文档这是什么协议,也不方便维护。除非真的有什么特别的场景,再单独处理。
    统一很重要。
    DOLLOR
        54
    DOLLOR  
       157 天前
    以前的项目,经常各种风格都有,包括 form 、xml 、json,甚至自立规范的 string 编码。
    现在明白了,还是 json 最省事,不管是简单的一个 msg:ok ,还是复杂深层嵌套的数组和对象,都能胜任。
    iseki
        55
    iseki  
       157 天前 via Android
    都想着省事,结果就是维护火葬场,大家一起费事~不如找好规范,折腾下 codegen ,麻烦一次后面就省事了
    jinliming2
        56
    jinliming2  
       157 天前   ❤️ 3
    @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 站在同等地位啊,具体走什么都取决于封装而已。]
    jinliming2
        57
    jinliming2  
       157 天前
    @Austaras 图片用 base64 的话,文件体积会变大 1/3 ,并且代码量都比 FormData 要多了……还不如直接用 FormData 来的简单,并且用 FormData 只会固定大几个字节。
    jqtmviyu
        58
    jqtmviyu  
       157 天前
    喜欢无脑 json, 希望 post 都用 body 传参.
    但后端说太麻烦要建实体类, 希望用 get 请求参数放在 query 和 params 里, 但真是别扭呀, 搜接口都不方便, 数据 query, params, body 都有, 乱乱的.
    tagtag
        59
    tagtag  
       157 天前
    什么都行,成套成标准就行,封装一下,用起来没有区别
    FightPig
        60
    FightPig  
       157 天前
    @Oktfolio 写 rails 的人表示从来都按这种来
    BigDogWang
        61
    BigDogWang  
       157 天前
    作为客户端开发,一般所有的请求都要有一个对应的 request 类,不论什么数据格式全盘接受
    siteshen
        62
    siteshen  
       157 天前
    作为一个后端,我几乎都是选择 json ,不给前端和客户端任何选择的机会。
    pengtdyd
        63
    pengtdyd  
       157 天前
    作为一个后端,是标准的制定者,其他人没资格谈条件!
    passerbytiny
        64
    passerbytiny  
       157 天前 via Android
    客户端是 Java Android 分支,前段是 Javascript **分支,后端接口的通信契约是 HTTP 协议、JSON 标准等,这本来就是相互独立的不同团体,不一样才是天为,一样了是才是人为。
    jobscolin
        65
    jobscolin  
       157 天前
    表示客户端从来没提过要求,后端要啥给啥。。。
    comoyi
        66
    comoyi  
       157 天前
    作为后端一直要求接口使用方 POST 使用 application/x-www-form-urlencoded ,文件 form-data ,然后不管几个字段都定义结构体接收
    DDDZZZFFF
        67
    DDDZZZFFF  
       156 天前
    post,json 一把梭
    rosu
        68
    rosu  
       156 天前 via iPhone
    对于客户端来说,还是 Json 方便扩展,不然后续接口加参数,传参地方都得修改。
    abersheeran
        69
    abersheeran  
       156 天前
    我认识的很多菜鸟前端都分不清楚这几种提交格式的区别,所以我写的 web 框架的参数注入功能会自动判断,不管啥类型都能解析。反正实践里,前端很满意,后端也很满意。🤭
    Austaras
        70
    Austaras  
       156 天前
    @jinliming2 没有啊,前端这边只需要封装个函数就完事了,乃至可以给 input 写个 directive 让它冒上来的就是 base64
    shayuvpn0001
        71
    shayuvpn0001  
       155 天前
    @abersheeran 确实没啥区别啊,不都是字符串么
    liuxue
        72
    liuxue  
       155 天前
    个人前端, 很不喜欢 users/{user} 这样传递参数的方式。如果页面上多个接口都需要 user 这个参数,如果 user = 123456.
    调试的时候就只能看到 123456.具体是哪个接口调用的查看起来不直观。
    risky
        73
    risky  
       155 天前
    我们这里还可以 application/excel 直接返回文件下载
    后端同学都感动哭了
    yaphets666
        74
    yaphets666  
       155 天前
    @jinliming2 请求肯定要统一定义的,不可能散乱的在各个组件中定义的,不然改起来好麻烦.
    关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   3279 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 05:10 · PVG 13:10 · LAX 22:10 · JFK 01:10
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.