比如说,按照约定后台应该返回这样的一个数据结构:
{
a: {
b: [] // 某数组
},
c: '某字符串'
}
但是有时候事与愿违,团队开发者一多,后台往往会返回缺斤少两或者奇怪的东西,导致错误,比如
{
a: null,
c: null
}
或者:
{
a: {
b: null
}
}
我知道可以通过逐个字段判空来解决,但这太麻烦了,而且一不小心就漏掉了什么地方。有没有一种工具,可以对这样的数据按照约定结构进行补全呢?
比如:
[]
{}
0
1
muziyue 2017-12-20 20:07:23 +08:00 6
想法不错,不过遇到这种情况找后端打一架比较管用
|
2
orancho 2017-12-20 20:10:17 +08:00
Protobuf 请。
|
3
264768502 2017-12-20 20:12:13 +08:00 via iPad
|
4
LancerComet 2017-12-20 20:22:46 +08:00 1
看了上文,实际上如果接口很多业务很个性,为了确保类型安全还是要写很多业务相关的过滤器,目前看来并没有什么特别好的偷懒方法.
在下所在项目目前的实践是为关键服务的接口写过滤器 + TS Definition,并会在代码审核时检查,说白了就是这个任务一点没省,只不过是平均了罢了. 期待有更好的偷懒实践. |
5
wxsm OP |
6
crysislinux 2017-12-20 20:26:15 +08:00 3
json schema 校验,放在后端的出口就好了,不符合 schema 的就直接报错让后端改,不然你补全了有什么用,你补的了代码补不了逻辑。
|
7
orancho 2017-12-20 20:27:14 +08:00
|
8
zjsxwc 2017-12-20 20:35:18 +08:00
必须要前后端都有一个约定才能解决楼主问题,不然缺斤少两的情况下,也无法判断出缺的那个字段是补成[]还是{}还是""还是 0
|
9
zjsxwc 2017-12-20 20:45:11 +08:00 1
2 个办法:
1. 类似 protobuf 辅助在代码上统一,*约定*通过编写 protobuf 消息文件来指定, 要改原来的代码 2. 用中间转发网关,*约定*通过在这个中间网关里通过图形界面配置,我记得有开源的 |
10
maemual 2017-12-20 20:46:23 +08:00 via Android
我觉得在后端数据无法通过工具约束的情况下,遇到这种错误的数据直接报错更好一点。否则用默认值,当作正常数据再写回到后端的话,以后坑更大。
|
11
Torpedo 2017-12-20 20:48:17 +08:00 1
之前的项目就是这样。服务代理了很多接口,接口文档都没有。他们的数据总是不稳定。
其实我理解这个问题有两点: 1.不管什么库,按照你说的那么做都要把数据结构描述一遍。 2.找出不符合的情况不难,那么我一个一个写呢。但是比较大的问题是:这么多字段,每个出问题了都是一个异常处理逻辑。 基于以上两点,1 明显应该是大家约定的,但是却约定不好。2 一个个写太多。 我们用了 react,所以比较好的方法是用 react16 的 componentDidCatch,封了一个高阶组件来统一处理页面模块出错。 本来这问题就是数据问题,哪个数据问题就修复哪个数据就行了。只是前端这里处理,不因为他们的数据问题让整个页面挂掉就可以了 |
12
cenqingbo 2017-12-20 20:52:49 +08:00
@crysislinux 作者贴出来的错误的 null 返回也属于正确的 json shema 吧
|
13
Terry05 2017-12-20 21:02:28 +08:00
没啥好偷懒的,一个个节点去判断
|
14
will0404 2017-12-20 21:09:47 +08:00 via iPhone
这绝对是后端的锅啊,为什么要前端做?在 api 输出的地方做类型检查就好了,前端加个 lib 增加多少流量考虑过吗
|
15
wxsm OP |
17
sensui7 2017-12-20 21:35:31 +08:00 4
参考这个视频:
|
18
jzhang 2017-12-20 21:43:24 +08:00 1
|
19
isbase 2017-12-20 21:53:51 +08:00
|
20
wanganjun 2017-12-20 21:53:52 +08:00 via iPhone
为啥没人说 graphql
|
22
kaneg 2017-12-20 22:09:37 +08:00 via iPhone
把后端返回的 json 合并到定义的默认 json,是不是就得到楼主想要的结果了?
|
23
aegisho 2017-12-20 22:14:40 +08:00 via Android
1.明确规范,出 bug 算到后端的责任
2.老老实实写防御性代码 3.考虑类似 json schema 校验补全 4. 我能(要)打十个 |
24
wxsm OP |
25
vinceguo 2017-12-20 22:48:23 +08:00 via Android
楼上有人提到 protobuf,那我就顺便说一下 thrift 吧。类似的东西
|
26
RorschachZZZ 2017-12-21 00:06:53 +08:00
这就是参数规范化的重要性。
|
27
Obelly 2017-12-21 01:44:26 +08:00
一种“天才”的解决方案,将所有非数字全部格式化成字符串,要处理数据再另行处理字符串文本内容……
|
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' |
29
crysislinux 2017-12-21 07:12:13 +08:00
@cenqingbo 不全是,当然 schema 也不能保证逻辑正确,但是能保证该在的 fields 都在,类型都对
|
30
wxsm OP @Mutoo 这种实际上就是逐个字段判断了。而且这个 defalt 有局限性,处理的只是 key 不存在的情况。万一存在而且是 null,那还是会有问题。还得再加判断。麻烦得很。
|
31
wotemelon 2017-12-21 09:02:41 +08:00 1
|
32
bfbd 2017-12-21 09:08:34 +08:00
Object.assign(retData, defaultData)
|
33
bfbd 2017-12-21 09:09:55 +08:00
写反了,应该是:newData = Object.assign({...defaultData}, retData)
|
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 文件 |
35
mougua 2017-12-21 09:34:11 +08:00
这种情况,我一般是买把菜刀放桌子上,然后叫后端同学来谈谈接口~~~~
|
36
YMB 2017-12-21 09:35:17 +08:00
我觉得开发 API,第一件事就是定义接口规范,第二是授权机制。
接口规范可以用一个类封装一下,授权机制可以用中间件过滤一下。 然后写业务逻辑,基本没什么问题。 |
37
th00000 2017-12-21 09:39:51 +08:00
我完全同意一楼的看法 出现这种情况直接把后端打残比较好
|
38
evolify 2017-12-21 09:39:57 +08:00
和楼主一样的情况。而且更离谱的是,对于为空 l 的字段,他们直接 ignore 了,说是什么发的数据少一点快一点,简直是扯淡的优化。之前好好的,这么一搞,我前端一堆 undefined. 现在我的做法是在接收后台数据时,手动重新赋值,所有字段都用我习惯的命名方式,不然他后台又一改字段或者说两个地方字段名不一致,那就 GG 了。
|
39
justfindu 2017-12-21 09:41:32 +08:00
这个完全不能做呀, 智能化了解你的接口数据, 比如你的示例 给的 b:null, 那我应该给 b 一个{} 还是一个[] 还是'' . 你会说你可以通过配置来确定某个接口给的数据是什么, 那为什么不直接跟后端沟通? 这才是正确的出路啊...不规范的接口以后都是痛. 难道你 APP 也要一个筛选?
|
41
wxsm OP @justfindu 因为前端对数据的类型是有“预期”的(按照约定)。比如说正常来说数组都是用来遍历的,但是后台就返回了个 null,导致遍历失败报错。如果我按照“预期”把它变成一个 [],那不就解决了。团队开发者一多,沟通成本很高,反正我提过很多次了,根本没人鸟我。
|
42
li746224 2017-12-21 09:50:52 +08:00
graphql 吧,虽然觉得前端收益大,后端搞起来麻烦
|
43
v2chou 2017-12-21 09:51:33 +08:00
我们后台就是这样
|
44
leemove 2017-12-21 10:05:16 +08:00
哎呀 现在每一个请求我都会 catch.最要命的的是超时.
|
45
justfindu 2017-12-21 11:01:33 +08:00
@wxsm 所以我说你要通过配置预期来格式化每一个接口, 接口数据一多, 你就死了. 虽然我是后端, 但是这锅明显要甩给后端. 你就不管, 只要不符合格式, catch 到错误, 你就提示数据无法获取 哈哈哈哈
|
46
ChristopherWu 2017-12-21 11:27:18 +08:00
这种一般后端做,如上面同学说的 json schema,不但验证 request,给前端 response 也验证了。
后端不上只能打一架了 |
47
yuxuan 2017-12-21 11:29:20 +08:00
明显后端的锅 楼主要强势一些 加 lib 是在牺牲前端性能来做
|
48
kenshinhu 2017-12-21 11:31:02 +08:00
有责任的后端都会把这个解决的
|
49
denano 2017-12-21 11:41:12 +08:00
和后端定好数据结构,给出 api 文档当然是最好的了,还有自己前端写个函数判断下返回值结构咯
|
50
paradoxs 2017-12-21 11:43:55 +08:00
我们公司的话,大概 这个样子
{ result: 000000 成功 999999 失败 22222 某某错误 msg: data : } |