比如和后端商定好了,返回的接口格式是: { "A": "", "B": [{}, {}] } 这时候后端说了,B 的数据有时候没有,如果没有的话就直接返回{A:""} 我让他返回{"A":"***", "B":[]}
哪种方案好?
1
pandanrain123 2021-01-26 14:50:38 +08:00
合理
|
2
atonku 2021-01-26 14:52:15 +08:00 4
前端说了算,毕竟线上问题都是后台加班
|
3
abelmakihara 2021-01-26 14:55:37 +08:00
后端是 map 一把梭的吗?
|
4
uselessVisitor 2021-01-26 14:55:52 +08:00
第二种逻辑上比较好,但是后台要多写逻辑处理
|
5
opengps 2021-01-26 14:57:38 +08:00 2
总的来说是合理的,不过为了互相方便,能提前协商就更好了。
强制 key 存在可能需要后端额外的开销,将 null 强制初始化一个默认值 |
6
anjianshi 2021-01-26 14:59:18 +08:00 6
我是喜欢第二种,我觉得好处如下:
- 逻辑清晰(该有的字段都有,不用另外看文档确认有哪些字段) - 出 bug 几率小,前端代码复杂起来不好保证所有处理这个字段的地方都妥善处理了空值,而后端只要在返回的地方处理一次就好了。 - 测试抓包排查看数据时也清楚 |
7
raaaaaar 2021-01-26 15:04:20 +08:00
并不麻烦,主要看前端的想法,之前我和一个前端合作也遇到过这个问题,我们是加上了的。
|
8
lovecy 2021-01-26 15:06:50 +08:00
你可以要求后端给到 B:[],但是你最好适配一下没有的情况。。。
|
9
redtea 2021-01-26 15:06:58 +08:00 via iPhone 6
属性没有,省流量。
|
10
lepig 2021-01-26 15:17:56 +08:00
个人觉得就算为空也要返回比较合理,这样对前端开发人员比较友好。
我一般返回之前先判断一下这个 list 是否为空,如果为空就定义一个空数组返回。 |
11
Gehrman 2021-01-26 15:19:35 +08:00
第二种前端更方便判断
|
12
Takamine 2021-01-26 15:30:36 +08:00 via Android
通常会用第二种,保持结构完整性。
|
13
lemon94 2021-01-26 15:41:22 +08:00
我是移动端,我们后端是返回{"A":"***", "B":null}
不过对我也没什么影响,用字典转模型的三方工具直接转就可以。 在使用的时候记得判空就好。 |
14
wangxiaoaer 2021-01-26 15:49:32 +08:00
空也要返回,是搞笑的吗?加入一个用户对象,里面嵌套了地址等信息,难道要返回:
{name:null,age:0,address:{postcode:null,street:null....},.....} ?? 我们一般的逻辑是:首先 null 跟空是不一样的,其次 json 序列化返回的时候自动过滤 null 值 |
15
egoistttt 2021-01-26 15:58:44 +08:00
第二种,其实如果用个 vo 返回,这种东西都不会很麻烦,可能只是后端偷懒,直接 map 返回给你吧
|
16
caiqichang 2021-01-26 16:00:51 +08:00
{A:"", B:{ C:"" }} 前端直接 B.C 没问题
{A:"", B:null} 前端直接 B.C 没问题 {A:""} 前端直接 B.C 报错 Cannot read property C |
17
caiqichang 2021-01-26 16:03:14 +08:00
Spring Boot 默认的 jackson 没有的属性会返回 null 而不是去掉
|
18
shaoyijiong 2021-01-26 16:04:28 +08:00
我们的话如果列表为空 就是 {"a":[]} 如果字符为空就是 {"b":null}
|
19
dengjscn 2021-01-26 16:04:56 +08:00 5
@caiqichang 大哥你 JS 学的不行啊,B 为 null 咋还能 B.C 呢?
|
20
joyhub2140 2021-01-26 16:05:59 +08:00
没有数据的字段,并不回返回对应的 key 了,因为大部分及格的 json 解析库都有对应的解析方法,jsonObj.opt(key, fallback),会判断如果没有对应 key 的数据,会返回 fallback 。
|
21
caiqichang 2021-01-26 16:09:26 +08:00
@dengjscn 所以说返回 null 前端取 B.C 不用再先判断 B 是否为 undefined,方便前端
|
22
iugo 2021-01-26 16:10:28 +08:00
根据具体业务分析, 前端可能需要额外操作, 比如 `if (res.B.length === 0) {}`.
但如果是 B 算主业务, 则无论如何都传. 但上文的 B 应该不是主业务. |
23
iugo 2021-01-26 16:12:40 +08:00
其实前端 `res.B ?? []` 直接解决问题. 兼容后端目前的两种可能.
|
24
ElmerZhang 2021-01-26 16:16:53 +08:00
两种方式都可以,看哪种语义上更合理一些,因为不返回 B 和返回 B:[] 是不一样的意思,不返回 B 相当于 B:null,null 值和空值的含义是不一样的。
|
25
trlove 2021-01-26 16:18:32 +08:00 2
个人觉得没有就直接字段都不返回。理由是:首先没有也返回,前端返回大量字段为 null 或者为空字符,不觉得难看吗 其次有些人可能有某些字段 有些人没有某些字段 但因为是一张表 全字段返回,就容易让人猜到一些关键信息字段。最后就是 难道前端展示信息的时候 对于不是必然有的字段 进行展示的时候 都不 if 一下吗 就直接用?不管数据介凡辉结构啥样,我觉得对参数要判断下是基本操作吧,万一碰上个辣鸡后端骚操作,你不判断数据直接展示,哪天突然来个字段没了啥的,然后页面报错或者啥的,直接影响用户,严重的到时候背锅的可是自己。 所以我是认为没必要返回,前端对于不是必然出现的字段进行判断,保命要紧,不能把命运交在别人手上
|
26
killergun 2021-01-26 16:22:54 +08:00
前后端可以约定好,怎么返回。
|
28
trlove 2021-01-26 16:29:40 +08:00 2
@darknoll 嗯嗯 我是认为没有就不返回。返回的太全,容易被人猜到核心设计。很多产品能够存活就是设计的好。全字段返回,基本一个表的字段差不多都被猜个七七八八了,有了表结构和流程原样复制产品就太简单了。再一个就是你是没碰到那种上百字段的,如果没有信息的也展示,真的吧后端搞死……还存在嵌套的问题。而前端只需要一个 if 就可解决所有字段不存在的问题……而且本身前端也得校验数据,所以相比之下我觉得不返回字段更好
|
29
nigelvon 2021-01-26 16:33:14 +08:00
一般来说空数组和 null 并不相等,不建议强行转换。
|
30
jiangshanmeta 2021-01-26 16:33:22 +08:00
b 是数组 则后端应该返回空数组 b 是对象 则应返回 null 没有和 null 是两个语义
|
31
dengjscn 2021-01-26 16:40:55 +08:00
@caiqichang 要不你控制台试试?
|
33
Rhonin 2021-01-26 16:48:55 +08:00 20
看来这个站还是后端多啊,这么奇葩的数据格式都在说合理?你们公司没有接口测试的吗?
|
34
YouLMAO 2021-01-26 16:59:22 +08:00
vue 的话一般使用 protobuf, 你的 json sjb 问题不存在
|
35
h82258652 2021-01-26 17:06:34 +08:00
要不就{"A":""},要不就{"A":"","B":null}
反正不可能是{"A":"","B":[]} null 和空数组本质上就是两个不同的东西,就像空字符串和 null,存数据库表现出来的就是不一样的 |
36
SkyLine7 2021-01-26 17:07:14 +08:00
第二种吧
|
37
jzmws 2021-01-26 17:08:35 +08:00
典型的 map
|
38
rabbbit 2021-01-26 17:09:26 +08:00
无所谓, 反正现在可以这么写
``` const a = {} console.log(a?.b?.c?.d || []) // [] ``` |
39
maemual 2021-01-26 17:10:57 +08:00
支持第一种。
不返回,或者返回 null,和返回空列表 /空字符串,语义上是不一样的。 |
40
maemual 2021-01-26 17:13:07 +08:00 2
@maemual #39 还有一种情况,比如产品要求上线一个功能,最后实现这个功能的数据就是 B 。如果前端、客户端一开始就支持不返回 B 就不展示这个功能的逻辑的话,未来哪一天,这个产品功能下线了,那么后端直接把字段一删,就再也不用管了。如果要求必须返回一个空列表或者空字符串,那么后端接口返回值里,始终得维护一个恶心的没用的字段。
|
41
shoushi 2021-01-26 17:13:47 +08:00
json 转的时候可以配置 null 值是否删除字段吧
|
42
jheroy 2021-01-26 17:24:52 +08:00
内部使用的接口直接私有协议,自己写协议文件,或者用 protobuf,这样不但性能好,还省流量。 公开协议才用 json,兼容性高,如果是公开协议了,文档肯定得写好。
|
43
keepeye 2021-01-26 17:28:03 +08:00
前端定义个默认 json,object.assign 一下即可吧。后端可能是个动态语言,如果是结构体序列化的应该是有字段的
|
46
Sparetire 2021-01-26 17:57:21 +08:00 via Android
类型的角度来讲显然第二种好,第二种的类型始终是数组,处理起来更加一致。第二种情况极端情况下一个接口几十个字段一半都在判空,漏一个出了 bug 就想骂人,而那一大坨判空操作在语法糖的帮助下看起来都显得臭不可闻,没想到本站这么多人喜欢 null 这种糟粕。。
突然觉得每个后端都应该把接口用 json schema 滤一遍,bug 从源头消灭掉 |
47
trlove 2021-01-26 17:57:46 +08:00
@Rhonin 我不知道你有没有看别人网站接口的习惯,就我观察来看,很多大厂都是第一种情况,没有字段都不返回。就比如 msg data 两个参数来说,很多大厂都是如果接口返回错误信息 那就只返回 msg 字段 看不到 data 字段了,如果业务正常返回数据 那 msg 就没了 只有 data 。而且 data 通常都是动态的,有时候可能是单条数据 有时候可能是单字符 有时候可能是数组,按第二种方式来,如果 data 为空,没数据的时候,那这个 data 是给它赋值空字符 还是空数组?还是给它 null?其次有些字段用不到的返回有什么意义呢,显得 json 长吗?而且一般这种处理都是后端通用处理方式,不会是每个接口单独去处理到底该返回空字符还是 null 还是空数组问题,单个接口都来一遍,碰到字段多的,嵌套多的,得写多少个循环多少个 if……
|
48
znyq2019 2021-01-26 17:58:42 +08:00 2
两边都做 . 别想着省事
|
49
zeropercenthappy 2021-01-26 18:05:33 +08:00
作为一个移动端开发,我支持第一种,数据看起来舒服,处理起来也不需要太多额外的操作。
可以省略,但是不能变。 如果一会儿是"B":[],一会儿是"B":"",那我就要喷人了。 |
50
laminux29 2021-01-26 18:20:23 +08:00
必然第二种方案,因为人都会犯错,第一种方案无法区分到底是 B 不存在,还是前端忘了回发 B 的值。
另外:B 不存在、B 存在但为空、B 存在不为空但为空数组等等,这些都是不同的逻辑。建议增加状态字段来区分这些情况。 比如前端应该这样返回: struct ResultData { ....string A; ....//Bstate:B 的状态码 ....// 0:B 不存在; 1:B 存在但为 null ; 2:B 存在且有值。 ....byte Bstate; ....//当 Bstate 为 2 时,允许 B 为空数组。 ....array B; . } |
51
guanhui07 2021-01-26 18:26:38 +08:00
第二种
|
52
trlove 2021-01-26 18:28:11 +08:00
@laminux29 加状态字段……然后一个接口 100 字段,外加 100 个状态字段,然后还得根据状态字段去决定是否渲染值…… 那为何不直接 if 字段 然后渲染…… 至于说的无法区分到底是 B 不存在还是前端忘了回发 B 的值,对于第二种,如果这个错误能犯,那你家状态字段,也可能会犯不判断状态的错误……这种问题就是自己的 bug 。对于第一种,只要你前端判断没有这个字段,至于后台是真有还是真没有,那是后端的事,出问题也是后端吧锅端着
|
53
cco 2021-01-26 18:33:53 +08:00
你的逻辑需要都有,那么是空值那就得都有,你的逻辑有判断,那就没啥毛病。
|
54
Paladinfeng 2021-01-26 18:37:36 +08:00
数组为空最好给个空数组,要不前端用起来不好用
|
55
IvanLi127 2021-01-26 18:38:33 +08:00 via Android
第二种方案好,合理。第一种方案为了性能?为了性能为什么还用 json ?就是懒!
|
56
AoEiuV020 2021-01-26 19:17:44 +08:00
我也觉得数据类型必需统一,有数据是数组,那没数据当然就是空数组了,你敢给 null 我就敢崩溃,
|
57
koolob 2021-01-26 19:30:15 +08:00
第一种呀。要知道出流量可都是钱呀。
|
58
gzf6 2021-01-26 19:33:19 +08:00
data?.B
|
60
ashmodeus 2021-01-26 19:52:42 +08:00
最好自己写兼容逻辑,凡是提前协商的在真正出线上问题时,都有可能变成甩锅的情况。
|
61
nicevar 2021-01-26 20:31:18 +08:00 1
第一种是合理的,早期在做手机应用的时候还是 wap 时代,那个时候的后端不可能按第二种给你传,本来稍微大点数据都得拆,你一堆空字段还传下来不被喷死。如今虽然网络快了,但是也架不住一大堆网站下发一堆垃圾数据,20 个字段有 5 个是必选的,其他的可选下发一堆空的,真的很蠢。
|
62
asAnotherJack 2021-01-26 20:38:22 +08:00
楼上好多说用的是 map,不见得,go 里面 list ( slice )零值就是 nil,不做处理 json 就是 null,加上 tag omitempty 就是直接不带零值的字段了。至于没值还要返回[],我个人是不乐意做的。
|
63
ichou 2021-01-26 20:47:30 +08:00 via iPhone
graphql
|
64
laminux29 2021-01-26 21:01:27 +08:00
@trlove
1.如果接口有 100 字段,那么外加 100 个状态字段是合理的。根据状态字段去进行判断是否要进行渲染,这也是合理的。 2.如果加了状态字段,前端犯了不判断状态的错误,那么很显然这里就只存在这一种错误了,这种错误容易发现,容易排查。但不加状态字段,错误的原因会更多,需要一条条去排查,费时费力。 总之,这种设计是加强鲁棒性的做法,你们这些萌新需要仔细体会,加强学习。 |
65
yazinnnn 2021-01-26 21:04:12 +08:00
b 没数据就返回空集合啊。。。
你们商量好就行 |
66
agdhole 2021-01-26 21:11:08 +08:00
前端把 es 开到最新,用 b?. 来取值(逃
|
67
Actrace 2021-01-26 21:26:38 +08:00
工程化的项目中,基本不存在的协商这种说法。
后端按产品需求考虑所有可能的情况,设计接口,然后文档化。 前端按照文档进行开发,各司其职,没有什么可以扯皮的地方。 |
68
fiypig 2021-01-26 21:36:30 +08:00 via iPhone
不管有没有,前端就几个判断吧,不然你那边很容易报错
|
69
gimp 2021-01-26 21:36:50 +08:00
第二种,没数据应该返回空数组,保证字段的类型相同,能减少前端很多不必要的判断,同时也有利于接口自动化测试。
之前调试几个接口,有时候没有字段,有时候回个 null,有时候回空数组,这种不稳定的接口真是一言难尽。 |
70
DreamSpace 2021-01-27 00:36:51 +08:00 2
个人理解这要根据业务逻辑来决定。
{"A":null} 代表属性 A 没有对应的数据。 {"A":[]} 代表属性 A 有对应的数据,但数据为空。 具体采用哪种交互得根据业务的真实逻辑来,而不是哪种方便用哪种。 |
71
lizytalk 2021-01-27 00:54:08 +08:00 via iPhone
也不是不合理。但是得确定好哪些是可能没有的,哪些一定有
|
72
TheWidowMaker 2021-01-27 01:00:45 +08:00 via Android
前后端打架现场…
|
73
lpbname777 2021-01-27 01:45:27 +08:00
@gimp 最烦这种的
|
74
lpbname777 2021-01-27 01:47:10 +08:00 1
用接口就只有一条规则,数据结构要稳定。Array/String 类型的字段不能返回 null,不能不返回
|
75
lpbname777 2021-01-27 01:50:55 +08:00
@znyq2019 或者就像这老哥说的,都校验 /处理,谁也别跑
|
76
kassadin 2021-01-27 02:16:43 +08:00 5
大家能沟通就文档约定,不能沟通就防御型编程,主动降低背锅率。
|
77
OHyn 2021-01-27 02:34:51 +08:00
都行,要明确好就行。
别 Swagger 上面写了返回 Array,到时候返回 null 或直接没属性。 |
78
linmq 2021-01-27 05:35:32 +08:00 via iPhone
我倾向第二种
|
79
jdlau 2021-01-27 08:20:44 +08:00 via Android
看到有大量 null 的情况,我有点好奇,这样的设计有没有问题呢?
|
81
tsanie 2021-01-27 08:35:04 +08:00
第一种第二种都行,但是就算是第二种方案,前端最好也要做一下 B 没有的容错吧
|
82
wangyzj 2021-01-27 08:37:17 +08:00
为空也得返回,减少 confuse
|
83
lrh3321 2021-01-27 08:46:11 +08:00 via Android
都合理,互相不信任防御性编程,到时候不容易出错
|
84
whileFalse 2021-01-27 08:48:32 +08:00
首先,前端能有多难处理一个不存在的属性?
其次,要说合理的话还是要具体分析。有的业务情况下,不存在和存在一个空数组是不同的状态,需要分别处理的。 |
85
mmdsun 2021-01-27 08:49:11 +08:00 via Android
对象空可以返回 null
数组空建议是返回空 [] |
86
john6lq 2021-01-27 08:52:16 +08:00 via iPhone
说返回 null 合理的不怪你写一辈子烂代码。
|
87
netnr 2021-01-27 08:52:17 +08:00 via Android
不合理
|
88
xianxiaobo 2021-01-27 08:52:22 +08:00
肯定是第二种啊,第一种容易出问题,必须让后端改成第二种,不然离职。
|
89
guisheng 2021-01-27 09:01:54 +08:00 via iPhone
如果没有接口文档建议写第二种,如果有我建议使用第一种。
|
90
ebony0319 2021-01-27 09:03:49 +08:00
我猜其实后端也一脸懵逼.序列化框架做的.第一种目前也存在,只是用的少了而已.
|
91
GoodKvm 2021-01-27 09:04:01 +08:00
第二种
|
92
p1gd0g 2021-01-27 09:05:05 +08:00
用 protobuf 吧。。。
|
93
ramcasky 2021-01-27 09:06:32 +08:00
@whileFalse 业务复杂还挺难处理的
|
94
weixiangzhe 2021-01-27 09:08:56 +08:00
主要是 null 前端不是很好处理,建议 request 那里处理一下,为 null 改为 undefined
|
95
roudancongji 2021-01-27 09:10:05 +08:00
盲猜一手用的 mongodb ?
|
96
lagoon 2021-01-27 09:11:21 +08:00
有多少公司能很好的维护更新文档的?
反正我见过许多老项目,最终都是要看代码来理解的。 {A:""},以后想要知道这接口只返回 A,还是可能会有 B,就比较麻烦了。特别是一些不怎么出现的参数。 接口按结构返回了,以后调一遍,看看结构,理解当时的接口情况简单多了。 |
97
EminemW 2021-01-27 09:13:03 +08:00 via iPhone
怎么可能返回 null……真有人这么写?
|
98
yaphets666 2021-01-27 09:16:04 +08:00 7
觉得第一种好的,不论你干了多少年,源码多熟算法多牛逼,你的同事一定讨厌你.
|
99
luhuisicnu 2021-01-27 09:16:06 +08:00
看场景吧,非必要的可选字段,前端检查到就展示,未检查到就不做处理,如果是必须字段,那么必须要返回 key,value 看场景给出
|
100
sonxzjw 2021-01-27 09:16:42 +08:00
从更好性能、更少重复工作来看,b 的提议更好。
1 是少传数据,2 是只要前端进行判断(可能不需要判断) 如果用 2 的方案,数据多传,后端还可能要进行判断来输出 b:[](也可能不需要),前端也要进行空判断(也可能不需要) 情况写明白了,那客观上选哪个方案一目了然了。主观的话就不谈了。 |