有没有这样一个 lib,可以帮 js 前端“清理”后台 api 返回的数据结构? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
wxsm
V2EX    程序员

有没有这样一个 lib,可以帮 js 前端“清理”后台 api 返回的数据结构?

  •  2
     
  •   wxsm
    wxsms 2017-12-20 19:56:39 +08:00 7089 次点击
    这是一个创建于 2920 天前的主题,其中的信息可能已经有所发展或是发生改变。

    比如说,按照约定后台应该返回这样的一个数据结构:

    { a: { b: [] // 某数组 }, c: '某字符串' } 

    但是有时候事与愿违,团队开发者一多,后台往往会返回缺斤少两或者奇怪的东西,导致错误,比如

    { a: null, c: null } 

    或者:

    { a: { b: null } } 

    我知道可以通过逐个字段判空来解决,但这太麻烦了,而且一不小心就漏掉了什么地方。有没有一种工具,可以对这样的数据按照约定结构进行补全呢?

    比如:

    • 数组默认为 []
    • 对象默认为 {}
    • 字符串默认为空字符串
    • 数字默认为 0
    50 条回复    2017-12-21 11:43:55 +08:00
    muziyue
        1
    muziyue  
       2017-12-20 20:07:23 +08:00   6
    想法不错,不过遇到这种情况找后端打一架比较管用
    orancho
        2
    orancho  
       2017-12-20 20:10:17 +08:00
    Protobuf 请。
    264768502
        3
    264768502  
       2017-12-20 20:12:13 +08:00 via iPad
    LancerComet
        4
    LancerComet  
       2017-12-20 20:22:46 +08:00   1
    看了上文,实际上如果接口很多业务很个性,为了确保类型安全还是要写很多业务相关的过滤器,目前看来并没有什么特别好的偷懒方法.

    在下所在项目目前的实践是为关键服务的接口写过滤器 + TS Definition,并会在代码审核时检查,说白了就是这个任务一点没省,只不过是平均了罢了.

    期待有更好的偷懒实践.
    wxsm
        5
    wxsm  
    OP
       2017-12-20 20:23:08 +08:00
    @muziyue 打得了现任打不了下一任,自己不做处理总会有被坑的一天。

    @orancho 这个好像是新的数据交换结构,新项目可以考虑,可是现有的基于 JSON 的项目怎么搞?

    @264768502 好像不是我想要的东西。
    crysislinux
        6
    crysislinux  
       2017-12-20 20:26:15 +08:00   3
    json schema 校验,放在后端的出口就好了,不符合 schema 的就直接报错让后端改,不然你补全了有什么用,你补的了代码补不了逻辑。
    orancho
        7
    orancho  
       2017-12-20 20:27:14 +08:00
    @wxsm

    现有项目的话只能靠沟通和管理了,当然你也可以试着迁移一下。
    P.S. 我司自从尝了 protobuf 的甜头之后大部分项目都迁移了过去。
    zjsxwc
        8
    zjsxwc  
       2017-12-20 20:35:18 +08:00
    必须要前后端都有一个约定才能解决楼主问题,不然缺斤少两的情况下,也无法判断出缺的那个字段是补成[]还是{}还是""还是 0
    zjsxwc
        9
    zjsxwc  
       2017-12-20 20:45:11 +08:00   1
    2 个办法:

    1. 类似 protobuf 辅助在代码上统一,*约定*通过编写 protobuf 消息文件来指定, 要改原来的代码

    2. 用中间转发网关,*约定*通过在这个中间网关里通过图形界面配置,我记得有开源的
    maemual
        10
    maemual  
       2017-12-20 20:46:23 +08:00 via Android
    我觉得在后端数据无法通过工具约束的情况下,遇到这种错误的数据直接报错更好一点。否则用默认值,当作正常数据再写回到后端的话,以后坑更大。
    Torpedo
        11
    Torpedo  
       2017-12-20 20:48:17 +08:00   1
    之前的项目就是这样。服务代理了很多接口,接口文档都没有。他们的数据总是不稳定。
    其实我理解这个问题有两点:
    1.不管什么库,按照你说的那么做都要把数据结构描述一遍。
    2.找出不符合的情况不难,那么我一个一个写呢。但是比较大的问题是:这么多字段,每个出问题了都是一个异常处理逻辑。

    基于以上两点,1 明显应该是大家约定的,但是却约定不好。2 一个个写太多。
    我们用了 react,所以比较好的方法是用 react16 的 componentDidCatch,封了一个高阶组件来统一处理页面模块出错。

    本来这问题就是数据问题,哪个数据问题就修复哪个数据就行了。只是前端这里处理,不因为他们的数据问题让整个页面挂掉就可以了
    cenqingbo
        12
    cenqingbo  
       2017-12-20 20:52:49 +08:00
    @crysislinux 作者贴出来的错误的 null 返回也属于正确的 json shema 吧
    Terry05
        13
    Terry05  
       2017-12-20 21:02:28 +08:00
    没啥好偷懒的,一个个节点去判断
    will0404
        14
    will0404  
       2017-12-20 21:09:47 +08:00 via iPhone
    这绝对是后端的锅啊,为什么要前端做?在 api 输出的地方做类型检查就好了,前端加个 lib 增加多少流量考虑过吗
    wxsm
        15
    wxsm  
    OP
       2017-12-20 21:10:09 +08:00 via iPhone
    @zjsxwc 你说的这种“网关”其实不切实际。这样一来架构会变得极其脆弱。

    @maemual 主要是用来显示的这一块,不往回发。一报错测试马上就找到前端来了,各种背锅。

    @Torpedo 你这个办法看起来不错,我这边也是 RN,明天试一下。谢谢。
    wxsm
        16
    wxsm  
    OP
       2017-12-20 21:13:46 +08:00 via iPhone
    @will0404 组织已经决定了,这个锅就 tm 前端来背。
    sensui7
        17
    sensui7  
       2017-12-20 21:35:31 +08:00   4
    参考这个视频:
    jzhang
        18
    jzhang  
       2017-12-20 21:43:24 +08:00   1
    isbase
        19
    isbase  
    PRO
       2017-12-20 21:53:51 +08:00
    @Torpedo 我觉得如果是后端数据的问题,那就该正常抛出错误让页面挂掉,否则你 catch 了错误继续运行下去可能会导致更严重的问题

    @wxsm 平时写代码的时候可以多用 ES6 的函数参数默认值
    wanganjun
        20
    wanganjun  
       2017-12-20 21:53:52 +08:00 via iPhone
    为啥没人说 graphql
    janxin
        21
    janxin  
       2017-12-20 22:08:36 +08:00
    @wanganjun 因为 graphql 没有什么收益,除了前端偷懒以外
    kaneg
        22
    kaneg  
       2017-12-20 22:09:37 +08:00 via iPhone
    把后端返回的 json 合并到定义的默认 json,是不是就得到楼主想要的结果了?
    aegisho
        23
    aegisho  
       2017-12-20 22:14:40 +08:00 via Android
    1.明确规范,出 bug 算到后端的责任
    2.老老实实写防御性代码
    3.考虑类似 json schema 校验补全
    4. 我能(要)打十个
    wxsm
        24
    wxsm  
    OP
       2017-12-20 22:17:34 +08:00 via iPhone
    @jzhang 看了一圈文档,貌似没有发现对缺失值的处理办法?

    @isbase 默认值只能解决很小一部分的问题。通常数据都会有深层次的结构。

    @kaneg 同上。
    vinceguo
        25
    vinceguo  
       2017-12-20 22:48:23 +08:00 via Android
    楼上有人提到 protobuf,那我就顺便说一下 thrift 吧。类似的东西
    RorschachZZZ
        26
    RorschachZZZ  
       2017-12-21 00:06:53 +08:00
    这就是参数规范化的重要性。
    Obelly
        27
    Obelly  
       2017-12-21 01:44:26 +08:00
    一种“天才”的解决方案,将所有非数字全部格式化成字符串,要处理数据再另行处理字符串文本内容……
    Mutoo
        28
    Mutoo  
       2017-12-21 06:22:07 +08:00
    1) json schema
    2) lodash _.get(obj, path, default) 方法
    https://lodash.com/docs/4.17.4#get

    var object = { 'a': [{ 'b': { 'c': 3 } }] };

    _.get(object, 'a[0].b.c');
    // => 3

    _.get(object, ['a', '0', 'b', 'c']);
    // => 3

    _.get(object, 'a.b.c', 'default');
    // => 'default'
    crysislinux
        29
    crysislinux  
       2017-12-21 07:12:13 +08:00
    @cenqingbo 不全是,当然 schema 也不能保证逻辑正确,但是能保证该在的 fields 都在,类型都对
    wxsm
        30
    wxsm  
    OP
       2017-12-21 08:45:28 +08:00 via iPhone
    @Mutoo 这种实际上就是逐个字段判断了。而且这个 defalt 有局限性,处理的只是 key 不存在的情况。万一存在而且是 null,那还是会有问题。还得再加判断。麻烦得很。
    wotemelon
        31
    wotemelon  
       2017-12-21 09:02:41 +08:00   1
    bfbd
        32
    bfbd  
       2017-12-21 09:08:34 +08:00
    Object.assign(retData, defaultData)
    bfbd
        33
    bfbd  
       2017-12-21 09:09:55 +08:00
    写反了,应该是:newData = Object.assign({...defaultData}, retData)
    vghdjgh
        34
    vghdjgh  
       2017-12-21 09:23:57 +08:00 via Android
    这种情况的解决方案就是接口文档中也提供一份语言无关的 protobuf 或 json schema 文件,然后收到数据时做验证
    如果用 typescript,我用 https://github.com/plantain-00/types-as-schema 通过 types 生成 json schema 或 protobuf 文件
    mougua
        35
    mougua  
       2017-12-21 09:34:11 +08:00
    这种情况,我一般是买把菜刀放桌子上,然后叫后端同学来谈谈接口~~~~
    YMB
        36
    YMB  
       2017-12-21 09:35:17 +08:00
    我觉得开发 API,第一件事就是定义接口规范,第二是授权机制。
    接口规范可以用一个类封装一下,授权机制可以用中间件过滤一下。
    然后写业务逻辑,基本没什么问题。
    th00000
        37
    th00000  
       2017-12-21 09:39:51 +08:00
    我完全同意一楼的看法 出现这种情况直接把后端打残比较好
    evolify
        38
    evolify  
       2017-12-21 09:39:57 +08:00
    和楼主一样的情况。而且更离谱的是,对于为空 l 的字段,他们直接 ignore 了,说是什么发的数据少一点快一点,简直是扯淡的优化。之前好好的,这么一搞,我前端一堆 undefined. 现在我的做法是在接收后台数据时,手动重新赋值,所有字段都用我习惯的命名方式,不然他后台又一改字段或者说两个地方字段名不一致,那就 GG 了。
    justfindu
        39
    justfindu  
       2017-12-21 09:41:32 +08:00
    这个完全不能做呀, 智能化了解你的接口数据, 比如你的示例 给的 b:null, 那我应该给 b 一个{} 还是一个[] 还是'' . 你会说你可以通过配置来确定某个接口给的数据是什么, 那为什么不直接跟后端沟通? 这才是正确的出路啊...不规范的接口以后都是痛. 难道你 APP 也要一个筛选?
    wxsm
        40
    wxsm  
    OP
       2017-12-21 09:42:52 +08:00
    @wotemelon 这个有这么点意思,好像是我想要的东西。谢谢!
    wxsm
        41
    wxsm  
    OP
       2017-12-21 09:48:23 +08:00
    @justfindu 因为前端对数据的类型是有“预期”的(按照约定)。比如说正常来说数组都是用来遍历的,但是后台就返回了个 null,导致遍历失败报错。如果我按照“预期”把它变成一个 [],那不就解决了。团队开发者一多,沟通成本很高,反正我提过很多次了,根本没人鸟我。
    MoozLee
        42
    MoozLee  
       2017-12-21 09:50:52 +08:00
    graphql 吧,虽然觉得前端收益大,后端搞起来麻烦
    v2chou
        43
    v2chou  
       2017-12-21 09:51:33 +08:00
    我们后台就是这样
    leemove
        44
    leemove  
       2017-12-21 10:05:16 +08:00
    哎呀 现在每一个请求我都会 catch.最要命的的是超时.
    justfindu
        45
    justfindu  
       2017-12-21 11:01:33 +08:00
    @wxsm 所以我说你要通过配置预期来格式化每一个接口, 接口数据一多, 你就死了. 虽然我是后端, 但是这锅明显要甩给后端. 你就不管, 只要不符合格式, catch 到错误, 你就提示数据无法获取 哈哈哈哈
    ChristopherWu
        46
    ChristopherWu  
       2017-12-21 11:27:18 +08:00
    这种一般后端做,如上面同学说的 json schema,不但验证 request,给前端 response 也验证了。
    后端不上只能打一架了
    yuxuan
        47
    yuxuan  
       2017-12-21 11:29:20 +08:00
    明显后端的锅 楼主要强势一些 加 lib 是在牺牲前端性能来做
    kenshinhu
        48
    kenshinhu  
       2017-12-21 11:31:02 +08:00
    有责任的后端都会把这个解决的
    denano
        49
    denano  
       2017-12-21 11:41:12 +08:00
    和后端定好数据结构,给出 api 文档当然是最好的了,还有自己前端写个函数判断下返回值结构咯
    paradoxs
        50
    paradoxs  
       2017-12-21 11:43:55 +08:00
    我们公司的话,大概 这个样子
    {
    result: 000000 成功 999999 失败 22222 某某错误
    msg:
    data :
    }
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5057 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 39ms UTC 08:35 PVG 16:35 LAX 00:35 JFK 03:35
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86