有一个接口会返回如下数据:
{
A: {a: 'a', b: 'b', c: 'c'},
B: {a: 'a', b: 'b', c: 'c'}
}
假设当 B 为空时,返回如下数据(因为后端固定了数据结构):
{
A: {a: 'a', b: 'b', c: 'c'},
B: {a: '', b: '', c: ''}
}
然后让前端自己去判断 B 是否为空,请问这样是否合理?
是否有相应的设计规范?
1
lepig 2020-04-13 11:23:32 +08:00
干倒后端你就是规范,反之就是“爹”
|
2
quan01994 2020-04-13 11:25:13 +08:00
打一架,谁赢了,谁就是合理。
|
3
Vegetable 2020-04-13 11:27:17 +08:00
不合理, 一级对象零值设计的有问题.
|
4
Coulson6 2020-04-13 11:27:54 +08:00
可以改的,设置字段空的话就不传,都可以定制。不过你判断一下也行,不方便就叫他改改
|
5
yukinomiu 2020-04-13 11:30:10 +08:00
有问题, "数据不存在"和空字符串还是有区别的, 这种表示方法会埋坑(比如如果业务上真的需要空字符的话, 就面临无法表示的尴尬). 设置下数据为空时序列化时忽略就可以避免这个问题, 但是你们的后端没做, 可能因为各种包袱, 也可能因为懒.
|
6
orqzsf1 2020-04-13 11:31:32 +08:00
没什么问题阿
|
7
SY413927 2020-04-13 11:35:24 +08:00
有问题吧
|
8
Aliencn 2020-04-13 11:36:54 +08:00
问题就是浪费带宽,增加了碳排放
|
9
hooopo 2020-04-13 11:38:58 +08:00 via Android 3
不合理 辣鸡后端
|
10
nicebird 2020-04-13 11:40:09 +08:00
无法区分空字符。
|
11
dilu 2020-04-13 11:40:34 +08:00
只要商量好,一切都不是问题
你说的这种情况,在我们公司,前端会特意要求这样做而不是给个空对象 规范只要制定好,不存在合不合理的问题。 |
12
est 2020-04-13 11:41:09 +08:00 7
这就是你们想要的「静态语言一时爽,JSON 输出火葬场」 。因为 A B 都是静态定死的 struct 。23333 。。。。
|
13
Bramblex2 OP 其实重点不是谁改方便,而是逻辑上是否合理。
比如我给你一个空盒子,和什么都不给你,逻辑上是完全不一样的。 |
15
wunonglin 2020-04-13 12:00:35 +08:00
B 应该为 null 或者 B: {a: null, b: null, c: null}
我一直认为把空字符串当做“没有”是坏习惯 |
16
Bramblex2 OP |
18
zhuisui 2020-04-13 12:06:14 +08:00 1
要么 B: null 要么 B: {},这才是 B 为空或空的默认值(遵从类型定义)
|
19
zencoding 2020-04-13 12:08:25 +08:00
我一直认为把空字符串当做“没有”是坏习惯 + 1
|
20
wyz123723 2020-04-13 12:08:34 +08:00 6
后端没给你传 a: 'null'就算不错了
|
22
superrichman 2020-04-13 12:23:25 +08:00 via iPhone
送礼送个包装袋给我,还要我猜里面送的是什么礼物???
|
23
wysnylc 2020-04-13 12:26:16 +08:00
合理
|
24
mlxy123123 2020-04-13 12:26:55 +08:00
@est 我看你是看不起我们全 Map 教
|
25
buffzty 2020-04-13 13:29:41 +08:00 1
方案 1: interface Resp{
A:{a: string, b:string, c: string}, B?:{a: string, b: string, c: string} } 方案 2: interface Resp{ A:{a: string, b:string, c: string}, B:{a: string, b: string, c: string}|null } |
26
fancy111 2020-04-13 13:33:24 +08:00
哪有什么设计规范,不过是前后端互相协调而已
|
27
chendy 2020-04-13 13:38:27 +08:00
建议打死,用个 null 会死么
|
28
Chenamy2017 2020-04-13 13:46:46 +08:00
后端不要把这些垃圾数据抛到前端去。
|
29
ZSeptember 2020-04-13 13:51:37 +08:00
看 API 定义,都可以讨论
一般是返回 null 或者不返回 key |
30
ChineseCabbage 2020-04-13 13:55:40 +08:00
不合理,把数据丢给前端处理的都是垃圾后端
|
33
Bramblex2 OP @chenqh 阴差阳错,当了一年前端 leader,然后再找工作的时候发现如果再去找其他方向的话,可能比较难拿到我理想的薪资,总之还挺蛋疼的
|
34
Yuicon 2020-04-13 14:00:24 +08:00
同样的工作 前后端谁做都可以 看来你们前后端关系紧张
|
35
cassyfar 2020-04-13 14:03:28 +08:00
后端来搞笑的吧 B 空的话是{}
建议 B 用 null 的,这是 B undefined,不是 B empty,还是有区别的。 |
36
Cowhitewhite 2020-04-13 14:09:20 +08:00
我们这都是听前端的,他们是大哥。
|
37
Bramblex2 OP @cassyfar 确切的说 undefined / null / empty 在逻辑上是不一样的,undefined 是不该有这个字段,null 是指有这个字段但是这个字段里面可能没东西,{} 是指这个字段里面有东西,但是没内容。
比如举个简单例子: profile: null 是指我们没有 profile profile: {} 是指我们有 profile 但是里面没内容 这是很大区别的。 |
38
Bramblex2 OP @Yuicon
其实我追求的是「正确的是什么」。在工作上的话必然有很多 dirty 的东西不可避免,但我觉得不能因为 dirty 而放弃对正确的追求,否则自己的下限会越来越低,当有机会能去做正确的事的时候,可能就会因为惯性无意识的选择 dirty 的方法而不是正确的方法,也就是所谓的初心变了 |
40
est 2020-04-13 14:45:20 +08:00
@Bramblex2 当然 Nullable Type 也能实现,写起来不觉得绕么。。
@tabris17 实现当然都可以实现。就是在静态语言里,膏药要随时到处贴上。。。 @mlxy123123 全 interface 教。。。 @Lonely 跟语言的确没啥关系。但是极有可能是全面依赖的东西传了一个固定形态的 struct 然后手上要输出 JSON 就直接序列化出去了。 |
41
vevillive 2020-04-13 14:47:15 +08:00
若是返数是这样的结构,那么,前端展示应该是取 a 、b 、c 的值,这时候,前端顺便判空就好了,因为还有可能 a 、b 、c 只有某个为空的情况。当然,要后端判断全为空的时候给你个空或者不给也行,但是前端的逻辑又要加多一层判断
|
42
Yuicon 2020-04-13 14:48:43 +08:00
@Bramblex2 追求正确没问题,不过最好是限制自身,你觉得返回格式不正确可以写工具转成自己想要的。之所以这样妥协只是觉得这种事很多时候争不出什么结论。
|
43
ayase252 2020-04-13 14:51:39 +08:00 via iPhone
问题在于主楼的接口定义暴露了后端的实现细节。哪一天空的定义变的话,前端还要跟着改
|
44
windychen0 2020-04-13 14:52:04 +08:00
我觉得吧,大概 B 为空的时候传成{A: {a: 'a', b: 'b', c: 'c'}}就好了吧。。。我们前端判断都是 if(data.B){//to do something}的
|
45
purensong 2020-04-13 14:52:15 +08:00
作为一名后端,规范是我来定,前端可以提意见,我尽可能满足,不满足就让她保留意见。。
|
46
tds 2020-04-13 15:00:51 +08:00 1
我觉得这是一个沟通问题,以前前端还专门让我装过这种数据,他图用起来省事。一两句代码花不了两分钟,何必搞得这么僵呢。。以后总会碰到一些可能前端不好做,后端好做,或者后端不好做前端好做的东西。真就一步不让,各做各的,最后对大家都不好。
|
47
oneisall8955 2020-04-13 15:13:10 +08:00
有问题,我觉得{A: {a: 'a', b: 'b', c: 'c'},B:null} 比较直观
|
48
Bramblex2 OP @tds
你说的对也不对。 对是因为工作上塞垃圾代码的确没有问题,反正能跑就行,没必要跟同事闹僵。 不对是是因为基于对技术的追求,不能降低自己对技术的审美标准。我自己写的接口和带的后端绝对不能给我写这种垃圾代码。 |
49
Bramblex2 OP |
50
ISSSSSSS 2020-04-13 15:51:47 +08:00
一般前端会要求传 B: {a: '', b: '', c: ''} ,而不是直接把 B 中的 abc 干掉。
|
53
raynor2011 2020-04-13 15:59:24 +08:00
很多时候前端要求这么传,因为前端懒得自己构造
|
54
feelinglucky 2020-04-13 16:02:20 +08:00
一句话:null 和 empty 的区别,显然不合理
|
55
wusheng0 2020-04-13 16:08:21 +08:00 via Android
个人认为让后端先做个判断比较好
|
56
Bramblex2 OP |
57
alienx717 2020-04-13 16:11:48 +08:00
我做后端,我都觉得这个设计的有点烂,不友好
|
58
ruby0906 2020-04-13 16:17:31 +08:00
我曾经就是这样一个后端,和公司的前端产生了类似的纠纷,我觉得你可以借鉴一下。
当时我先写好了接口文档,前端看了也没提出什么意见,后来他实现的时候,提出各种要求,我没有同意。最后前端按我定的标准实现了。 当我以为一切都 OK 的时候,这个前端写了一封万字信,发给部门领导以及所有技术同事,描述他的心理感受,前后端标准,委婉吐槽等等。。 当时就觉得很难受,我要不要和他公司范围邮件辩论。不辩论吧,被人含蓄的吐槽。辩论吧,又是一件小事,懒得写俺么多字,又不想升级这件事。最后以我的忍耐告终。那感觉就像吃了一记闷亏。 所以,楼主你看看,要不要学习我那同事。。给公司领导和全部技术同事发一封吐槽信。。绝对比来这里找认同感心理会舒服多了。 |
59
MonoLogueChi 2020-04-13 16:22:41 +08:00
感觉不合理,不是固定结构不合理,是输出 '' 代表 null 不合理。
具体固定结构是否合理,还要看具体使用情况,我是搞后端的,一般我会输出 { “A": { "a": "a", "b": "b", "c": "c" }, "B": { "a":null, "b": null, "c": null }, } |
60
Hstar 2020-04-13 16:22:53 +08:00
这破结构我知道,前端需要,因为他们懒得判断 B 这一层到底是不是一个空对象,直接进入最后一层去判断
后来吃饱了趁着还构造一个这样的结构啊 |
61
noobsheldon 2020-04-13 16:30:18 +08:00
让我们先来定义一下“合理”中的“理”,不然公有公的理,婆有婆的理。/doge
|
62
LokiSharp 2020-04-13 16:32:14 +08:00 via iPhone
前端用 TS 就没这么多扯皮的了
|
64
MonoLogueChi 2020-04-13 16:35:02 +08:00
再补充一下 #59,我是写 C#的,"B": null 和 "B": { "a":null, "b": null, "c": null } 是完全不一样的,在 C#里,"B": null 表示 B 对象是 null , "B": { "a":null, "b": null, "c": null } 表示对 B 对象初始化过后,B 内的元素都为 null,用代码说就是
var B; 或者是 var B = null; var B = new B(); 或者是 var B = new { a = null, b = null, c = null } |
66
Exin 2020-04-13 17:05:14 +08:00
设计接口的时候都面向前后端沟通语言进行设计,楼主的情况就应该是按 JSON 设计,或讲究点来说是 JSON schema,设计完了前后端再各自向自己的语言转换,私以为这是最稳妥最不容易撕的。
就像人与人讲话,一个讲中文( JavaScript )的好,一个讲英文( Python )的棒,根本讲不出结果。站到中间地带才行。 当然实际执行的时候通常后端比较强势,照着自己语言方便就给了一些 JSON 的 hack 用法,这属于沟通问题了,是另一回事。 |
67
Bramblex2 OP @cassyfar
你的办公室里面有三个工位分别是 A, B, C 。 那 A 工位没有人和没有 A 工位逻辑上是一样的吗? 没有 profile 字段对应根本没有 A 这个工位。 profile: null 对应 A 工位上没有人。 profile: {...} 对应 A 工位上有个 {...} |
68
tomwan 2020-04-13 17:07:25 +08:00
B 为空你就返回 null 啊
|
69
Bramblex2 OP @ruby0906 说句不好听的哈,我找认同感发篇文章绝对比在这讨论强,起码我发文章还有粉丝看,一般都会认同我,何必来这里找不自在呢?我只想从技术上面逻辑上面来讨论这个问题,仅此而已。真的别以己度人。
|
70
ai277014717 2020-04-13 17:12:36 +08:00
根据业务需要,B 中的 a,b,c 是否需要单独判空。不需要直接不要返回 B 就好了。只需要判空 B 就好了。
|
71
brader 2020-04-13 17:13:02 +08:00
个人看法,其实我觉得大家说的两种都没有问题,关键有两点:1 、该项目主要由谁来制定标准,该标准是否在各个客户端兼容性良好。2 、风格要统一。
什么是风格要统一呢?就是比如:你这个项目,数据结构用的是第一种,那就从头到尾都用第一种风格;用第二种亦是如此。 满足了这两点,我觉得前后端沟通成本就能有效降低,达成共识后,双方也就不再会纠结,这个接口怎么返回这种,那个接口怎么返回那种。 那么说下,既然风格统一有这么多好处,还会出现多风格的接口呢?出现这个往往都是有历史原因,经手人比较多,后来的人,不够了解前人的风格和做法,最后就造成了这种局面。 如果你看不惯目前的局面,要坚持自己的标准,那么请统一它、重构它。请问你做好这样的决心了吗?没有的话,请不要吐槽它,因为你自己也并不想花时间去改造它 |
73
dorentus 2020-04-13 17:17:43 +08:00
不合理。
前端遇到 B: {a: '', b: 'a', c: ''}算什么? |
74
brader 2020-04-13 17:20:59 +08:00
@Bramblex2 既然自己有主导权,也在重构,那么你可以做到统一风格了,我认为,你无论采用哪一种风格的接口,和前端解释一次,说之后都是采用此种风格,我相信一个能正常沟通的前端,都不会去纠结这个东西。
如果你仅仅是想知道,那种风格看起来比较标准,我平时是比较喜欢:B:null,前端有提出要求的话,我也是很乐意改的 |
75
star7th 2020-04-13 17:26:02 +08:00
如果我是那个前端,后端这样写接口给我的我我绝对吐槽回去。
|
76
thet 2020-04-13 17:29:12 +08:00 via iPhone
无法区分对象空和字符串空值,正常的应该返回 Null 或不传吧,不过这也要看你们团队了
|
77
CasualYours 2020-04-13 17:38:58 +08:00
不合理。
当后端接口返回: { A: {a: 'a', b: 'b', c: 'c'}, B: {a: '', b: '', c: ''} } 你完全不能区分 B 是 null 还是 {a: '', b: '', c: ''},当然也不能排除说你们的业务定义中 B 和 {a: '', b: '', c: ''} 是一致的。 我认为的接口设计规范就是在满足需求定义的前提下,前后端协商到达双方的最大便利,从而简化开发流程。 |
78
CasualYours 2020-04-13 17:42:07 +08:00
@CasualYours
当然也不能排除说你们的业务定义中 B 和 {a: '', b: '', c: ''} 是一致的。 修改为: 当然也不能排除说你们的业务定义中 null 和 {a: '', b: '', c: ''} 是一致的。 |
79
cassyfar 2020-04-13 17:43:33 +08:00
@Bramblex2 A : {} 对应工位 A 没人,A : {1: {...}} 对应 工位 A 有员工,ID 为 1
没有工位 A 的情况是以下,A 不会出现在返回中。 Data: { B: {1: {...}} } |
80
zhang77555 2020-04-13 17:48:39 +08:00
具体场景具体分析,没有场景只谈设计没啥意义, 一般来说是会区分 null 和空串.
|
81
dioxide 2020-04-13 18:53:42 +08:00
你需要 ES 的 Optional Chaining 特性,
|
82
imbacc 2020-04-13 19:37:05 +08:00
前端拦截处理下就可以了。又不是不能用[dog]
|
83
ironMan1995 2020-04-13 19:50:55 +08:00 via Android
最近两个项目我和后端们配合是我根据功能定义接口格式给他们,然后大家觉得还行就用我定义的。如果后端不好实现就妥协,反正没闹过矛盾。
|
84
wangyzj 2020-04-13 20:07:12 +08:00
{
A: {a: 'a', b: 'b', c: 'c'}, B: {a: '', b: 'b', c: 'c'} } 这算 B 存在还是不存在? |
85
adoyle 2020-04-13 20:21:26 +08:00
> 请问这样是否合理?
对前端合理,还是对后端合理,这要看每个研发角色各自的上下文。通常来说,说不合理只是现有的技术栈不容易实现或者不兼容。我认为这没有通用的答案,因为这是跟具体项目和人相关的。 > 是否有相应的设计规范? 我觉得可以针对返回的数据结构设计一套类型系统。比如 A 类型、B 类型,它们有哪些可选字段、必选字段,字段类型是什么,可以用 JSON Schema 来表达。 然后定义空类型的固定表达,比如类型是字符串的 a 是空的情况,用 `{a: null}` 还是 `{a: ''}` 还是 `{}` 来表达;类型是数组的字段 b 用 `{b: []}` 还是 `{}` 来表达?统一风格就好。 或者直接用 GraphQL,你可以参考它的类型系统 https://graphql.org/learn/schema/#type-system 。 至于具体构造哪些类型,这是从业务角度来思考的。 最终你们会约定出一套 Schema 文档,以此为约束,互不侵犯。 |
86
hxse 2020-04-13 20:22:35 +08:00
这么较真, 老板给了你多少钱
|
87
dddd1919 2020-04-13 22:55:17 +08:00
严格来说
B: {a: '', b: '', c: ''} B: {a: null, b: null, c: null} B: {} B: null 这几种看起来都是在表达 [空] 这个概念,但每个结构表达的场景都是有区别的,你所说的空到底指的是哪一种,那就用哪一种,表达简单直接最好 |
88
lewinlan 2020-04-13 23:01:33 +08:00 via Android
要看具体的业务含义。
B:{a:'',b:''}是零值,B:null 是空值。 不过看你的描述应该用后者~ |
89
Jooooooooo 2020-04-13 23:52:07 +08:00
有风格
没有规范 |
90
CantSee 2020-04-14 08:43:25 +08:00
用 null 好点吧
|
91
p1gd0g 2020-04-14 09:01:22 +08:00
为啥不用 protobuf 呢。
|
92
jrient 2020-04-14 09:40:35 +08:00
这个得区分业务场景
|
93
jrient 2020-04-14 09:42:29 +08:00
比如 你需要根据 b[a]b[b]b[c]渲染,那这样就没什么问题
如果 b 是一个整体,需要整体非空判断,那这样设计就有问题 具体情况具体处理 |
94
cszchen 2020-04-14 10:58:18 +08:00
把前端后端一起干了,干我一样就没有这种烦恼了
|
95
encro 2020-04-14 10:58:22 +08:00
结构应该表意,这是写代码基本规范,应该尽量遵守。
users:null vs users:[] 通常后者能明确告诉我们这是一个空的 User 列表 user:{} vs user:null 通常后者表示这个用户不存在而不是这用户存在但是属性为空 user: {id:''} vs user:{id:null} 区别是一个表示 id 为空字符串,一个表示 id 没有设置 user:{orders:[]} vs user:{orders:null} 当然选前者 book:{author:null} vs book:{author:''} 当然选前者 book:{author_name:null} vs book:{author_name:''} 应该还是选前者表示作者名未设置而不是被设置未空字符串,但是这条动态类型语言比较难办,那么可以商量来。 以上可以衍生到数据库设计上。 如果以上很难办, 通常是因为缺少一个合适的框架, 比如 django rest 和 yii rest 只需要数据库设计合理通常就没这些问题。 |