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

同事为了 JSON 怎么写吵起来了!请各位断案!

  •  
  •   codeismylife · 2019-12-16 14:42:11 +08:00 · 32906 次点击
    这是一个创建于 1802 天前的主题,其中的信息可能已经有所发展或是发生改变。

    A 同事:

    [
    	{
    		"192.168.1.2": {
    			"Memory": "10%",
    			"HardDisk": "25"
    		},
    		"192.168.1.1": {
    			"Memory": "25%",
    			"HardDisk": "10"
    		}
    	}
    ]
    

    B 同事:

    [
    	{
    		"ip": "192.168.1.1",
    		"Memory": "10%",
    		"HardDisk": "25"
    	},
    	{
    		"ip": "192.168.1.2",
    		"Memory": "25%",
    		"HardDisk": "10"
    	}
    ]
    

    我认为 B 写的是对的,但是不知道怎么科学地反驳 A。A 这么写好吗?不好的话 A 的问题在哪儿呢?

    342 条回复    2019-12-28 23:33:44 +08:00
    1  2  3  4  
    ClericPy
        201
    ClericPy  
       2019-12-16 23:23:38 +08:00
    不说怎么用, 谁知道 A 和 B 怎么想的, 复杂度又不是只考虑取值

    问 CTO 去
    f056917
        202
    f056917  
       2019-12-16 23:26:57 +08:00
    我是前端,用哪种看使用场景,但是大多数时候我都希望是 B
    wuethan
        203
    wuethan  
       2019-12-16 23:50:25 +08:00
    团队开发,A 的写法就是在找麻烦
    liukanshan
        204
    liukanshan  
       2019-12-17 00:08:35 +08:00   ❤️ 1
    还是吃的太饱了
    gowa
        205
    gowa  
       2019-12-17 00:51:02 +08:00
    伙计,,A 是列表,,B 是列表内一个 map 对象啊。

    如果是手动解 MAP 转 Java 实体类,你让 B 来解一下试试。。

    不想找麻烦的一般都用 A,
    gowa
        206
    gowa  
       2019-12-17 00:51:31 +08:00
    @gowa 说反了。。。
    jismhxjr
        207
    jismhxjr  
       2019-12-17 03:09:33 +08:00
    站 B
    ericgui
        208
    ericgui  
       2019-12-17 04:33:24 +08:00
    你们看来还是需要用 typescript

    用了 ts,就不会有 A 这种沙雕写法出现了。
    ericgui
        209
    ericgui  
       2019-12-17 04:40:11 +08:00   ❤️ 1
    包括但不限于 java,typescript,C#,C,C++等各种静态类型语言

    凡是用动态语言的,都会出现类似 A 的奇葩
    lele2019
        210
    lele2019  
       2019-12-17 05:52:24 +08:00
    大部分情况下是 B 方法,不过还是要考虑使用场景,或许你们的场景可能用 A 方法更合适。。要不怎么有这种争论呢。!
    nifury
        211
    nifury  
       2019-12-17 06:09:14 +08:00
    @ericgui 但是 A 这样有什么问题吗? A 虽然反直觉但是一样可以反序列化成 Map<String, Data>呀,而且查询还方便
    xcstream
        212
    xcstream  
       2019-12-17 06:15:17 +08:00
    B 有顺序 信息量更大 A 方便查找
    yukiloh
        213
    yukiloh  
       2019-12-17 07:26:21 +08:00 via Android
    ip 做 k 怎么拿…
    matepi
        214
    matepi  
       2019-12-17 08:29:06 +08:00
    单纯拿 ip 查东西的话显然是 A 啊
    ip 当然是要拿来当 key 查,又不用有序
    但是你们如果有进一步的类似 ip 要变、通用反射框架必须值化之类的需求另说
    dengtongcai
        215
    dengtongcai  
       2019-12-17 08:33:48 +08:00 via iPhone
    b 规范,如果一种特定场景,a 才考虑,但是一般是 b
    vuevue
        216
    vuevue  
       2019-12-17 08:44:23 +08:00 via Android
    A 吃太饱了
    J2s
        217
    J2s  
       2019-12-17 08:46:19 +08:00
    用 A 的地方能用 B,用 B 的地方有时候用不了 A
    fatpower
        218
    fatpower  
       2019-12-17 08:47:13 +08:00
    B 有疑问?
    kokutou
        219
    kokutou  
       2019-12-17 08:48:08 +08:00
    站 B
    happilylb
        220
    happilylb  
       2019-12-17 08:49:28 +08:00 via Android
    我的小米 9 屏幕指纹版早上醒来发现用不了然后去设置密码里面看指纹解锁消失了……才用一个月。。
    waterlaw
        221
    waterlaw  
       2019-12-17 08:49:34 +08:00 via Android
    选 B, 同一实体尽量使用相同结构,A 也有他的使用场景
    mmixxia
        222
    mmixxia  
       2019-12-17 08:54:57 +08:00
    B 的列表是同构的。解析的话代码会简单很多,而且易用。
    c0011
        223
    c0011  
       2019-12-17 09:00:25 +08:00
    如果使用数据是把 ip 当做索引,那么 A 这种是对的。
    如果不是把 ip 当做索引,那么使用 A 的时候,一样需要全部遍历一下。这样的话,A 这样属于增加复杂性,提前优化,肯定是不建议的。
    CantSee
        224
    CantSee  
       2019-12-17 09:08:14 +08:00
    b 好[手动 dog]
    Youngxj
        225
    Youngxj  
       2019-12-17 09:11:39 +08:00
    我也喜欢 b
    nnnToTnnn
        226
    nnnToTnnn  
       2019-12-17 09:15:32 +08:00
    A 可以解析不?
    B 可以解析不?

    ---------------------------

    如果都能解析,干嘛纠结到底选择 A 好还是选择 B 好? 反正我是一个写前端的,写啥我都能解析,实在不行我就在 ts 里面搞个实体把你们这群后台的人给隔离开,自己写适配器 [doge]
    python
        227
    python  
       2019-12-17 09:16:00 +08:00 via Android
    看来大家都喜欢 B
    happilylb
        228
    happilylb  
       2019-12-17 09:16:01 +08:00 via Android
    @nnnToTnnn 哭哭,我的小米 9 屏幕指纹版早上醒来发现用不了然后去设置密码里面看指纹解锁消失了……才用一个月
    nnnToTnnn
        229
    nnnToTnnn  
       2019-12-17 09:17:24 +08:00
    你们就是吃的太饱了,有这点时间纠结到底是选择 A 还是选 B,代码都写完好几遍了。
    waphole
        230
    waphole  
       2019-12-17 09:18:42 +08:00
    无脑站 B
    nnnToTnnn
        231
    nnnToTnnn  
       2019-12-17 09:19:21 +08:00
    @happilylb 让我猜猜,估计是晚上更新升级新系统导致的,要不回退版本试试?
    waltcow
        232
    waltcow  
       2019-12-17 09:23:13 +08:00
    站 B
    saltedFish666
        233
    saltedFish666  
       2019-12-17 09:25:00 +08:00
    一般情况我建议 B,但是 A 这种你不能说他错,A 的话查找起来可能快一点,但我觉得毫无意义
    nnnToTnnn
        234
    nnnToTnnn  
       2019-12-17 09:25:15 +08:00
    @ericgui #209 无论是第一种还是第二种,这都是非常标准的 JSON 格式,至于前 /后台是用框架直接解析成 DTO 还是采用 JSON 库都很好解析(如果无法解析,那就是开发水平问题)。

    一个 JSON 解析都要争论的话,那么是不是该反思一下工作是不是太饱和了?
    charlieputon
        235
    charlieputon  
       2019-12-17 09:25:40 +08:00 via Android
    A 是沙币,这帖子竟然有 200+评论也是醉了。。
    gimp
        236
    gimp  
       2019-12-17 09:25:45 +08:00
    A 同事为什么要在对象外边再套个列表呢,取值多不舒服。
    as5739
        237
    as5739  
       2019-12-17 09:25:57 +08:00
    曾经我也写过 A,后来被前端小姐姐逼着改成 B 了。。
    zxiso
        238
    zxiso  
       2019-12-17 09:26:26 +08:00 via Android
    对于后端来说,我比较喜欢 a,因为可以映射为 map k v 的形式,可以方便的判断某个 ip 是否存在,然后来取值。对于前端来说 a 形式不友好,很多控件都是只支持 b 形式,如果要用 a 形式还需要自己处理。总的来说的话,b 会更通用一些,而且一般用 b 的话前端不会怼你。
    aoaione
        239
    aoaione  
       2019-12-17 09:27:58 +08:00
    作为前端需要返回 a 的情况比较少 一般都是需要 b 这种结构
    HENQIGUAI
        240
    HENQIGUAI  
       2019-12-17 09:29:20 +08:00
    遇到一个需求,将数据按照某某属性分组,传给前端,前端直接显示

    resultMap = problems
    .stream()
    .filter(i -> StringUtils.isNotEmpty(i.getTaskName()))
    .collect(Collectors.groupingBy(Problem::getTaskId, LinkedHashMap::new, Collectors.toList()));

    然后遍历 resultMap.entrySet(),取出来 key 和 value
    最后做成的东西就是长这个鬼样子

    [ {
    "taskName" : "XXXXX",
    "list" : [ {
    "taskId" : "481",
    "taskDetailId" : 518}]

    }]

    代码写的我都难受。。
    dangyuluo
        241
    dangyuluo  
       2019-12-17 09:29:23 +08:00
    谁钱多听谁的
    fancy111
        242
    fancy111  
       2019-12-17 09:29:40 +08:00
    苹果和梨子哪个好吃???
    具体情况具体分析,A 的值可以直取,B 的需要遍历。但是 B 可以重复 IP,A 只适合定量。
    nnnToTnnn
        243
    nnnToTnnn  
       2019-12-17 09:31:19 +08:00
    @zxiso

    A 转 B
    ```
    const data = [
    {
    "192.168.1.2": {
    "Memory": "10%",
    "HardDisk": "25"
    },
    "192.168.1.1": {
    "Memory": "25%",
    "HardDisk": "10"
    }
    }
    ]
    const newData = []
    Object.key(data[0]).forEach((key)=>{
    newData.push({
    ip: key,
    ...data[0][key]
    })
    })

    console.log(newData)

    ````

    A 转 B 也很简单啊。
    WebKit
        244
    WebKit  
       2019-12-17 09:34:08 +08:00
    如果后端返回 A,我会让他改成 B
    shengchao
        245
    shengchao  
       2019-12-17 09:34:54 +08:00
    我是前端,后端给我的通常是 B,但有时候为了业务方便,我自己会写一个方法,变成 A 的形式。
    用 A 的原因:有时候我有 Key,可以直接使用对应的 Value,不需要再次循环,比如这个 JSON 很大的时候。
    ```json
    [
    {
    "192.168.1.2": {
    "ip": "192.168.1.2",
    "Memory": "10%",
    "HardDisk": "25"
    },
    "192.168.1.1": {
    "ip": "192.168.1.1",
    "Memory": "25%",
    "HardDisk": "10"
    }
    }
    ]
    ```
    z1154505909
        246
    z1154505909  
       2019-12-17 09:36:21 +08:00
    A 这种我怕我会被公司前端打死
    sirius1024
        247
    sirius1024  
       2019-12-17 09:36:42 +08:00
    A 唯一的好处是 Key 永远不可能重复。
    gitopen
        248
    gitopen  
       2019-12-17 09:37:16 +08:00
    一句话:插入 mongodb 时 key 不能有`.`啊
    mayufo
        249
    mayufo  
       2019-12-17 09:37:48 +08:00
    站 B
    pyfan
        250
    pyfan  
       2019-12-17 09:40:27 +08:00
    能先说一下你们公司这个 json 结构使用场景吗
    crist
        251
    crist  
       2019-12-17 09:45:43 +08:00
    虽然 B 看起来比 A 要更加规范,但其实 A 方式更加利于查找,利于性能。
    flashing
        252
    flashing  
       2019-12-17 09:46:18 +08:00
    得有个 background 吧,不是简简单单怎么设计的问题,现在信息不全不太好判断出发点是什么。
    话说 A 的方案本质上 json 是个 object,property 的名字可以是个 ip 地址这样有特殊符号的吗?
    qilishasha
        253
    qilishasha  
       2019-12-17 09:49:15 +08:00 via iPhone
    b 扩展容易 很灵活 是标准的数据表写法(既然如此,加一个 id 怎么样😂)
    lihongjie0209
        254
    lihongjie0209  
       2019-12-17 09:53:28 +08:00
    @crist #251
    什么叫性能? 在多大的数据量和什么样的硬件上会有明显的区别? 是否做过 profile?
    KuroNekoFan
        255
    KuroNekoFan  
       2019-12-17 09:56:04 +08:00
    json 数据应该自描述
    yulgang
        256
    yulgang  
       2019-12-17 09:56:22 +08:00
    这该不会是从 zabbix 里拿出来的东西吧😂
    dotw2x
        257
    dotw2x  
       2019-12-17 09:58:49 +08:00
    哈哈 早上刚好看到个类似问题,有人吐槽微信小程序订阅消息接口返回值的反人类设计😀
    小程序返回值:
    {
    errMsg: "requestSubscribeMessage:ok",
    zun-LzcQyW-edafCVvzPkK4de2Rllr1fFpw2A_x0oXE: "accept"
    }

    大家期望的返回值
    {
    errMsg:"requestSubscribeMessage:ok",
    data: [
    { tmplId:"zun-fytytytrytrytr", result:"accept"},
    { tmplId:"zun-fyrdrtdtrds5eu0", result:"reject"}
    ]
    }

    详情: https://developers.weixin.qq.com/community/develop/doc/000028cf058e78010e590be2255400
    iFlicker
        258
    iFlicker  
       2019-12-17 09:59:33 +08:00
    转实体类少一个对象层级 ,一句话驳回去了
    mizzle
        259
    mizzle  
       2019-12-17 10:11:00 +08:00 via Android
    很明显大多数人没有搞清楚字面量对象和 json 之间的区别。如果作为字面量对象,A 和 B 没有高下,只是使用场景不同。作为 json,B 更好。
    unco020511
        260
    unco020511  
       2019-12-17 10:23:46 +08:00
    你这个 ip 是固定的还是不定的,相对来说如果是固定的 A 写法取值方便一些(相对),如果是不固定或者后期可能有更改,那就 B,反正 B 是万金油的,更灵活
    unco020511
        261
    unco020511  
       2019-12-17 10:24:48 +08:00
    @unco020511 移动端开发角度
    southsala
        262
    southsala  
       2019-12-17 10:26:17 +08:00
    A 写的不是 Json,看 Json 定义 A collection of name/value pairs,不确定的数据怎么能做 name 呢
    binux
        263
    binux  
       2019-12-17 10:35:18 +08:00   ❤️ 1
    @dotw2x #257 这个就是 A 合适的使用场景:
    1. key 唯一
    2. key 确定

    B 当然也行,但是所有后端不会处理的,就是菜,没别的原因。
    darknoll
        264
    darknoll  
       2019-12-17 10:37:16 +08:00
    这种贴也能回这么多
    DeWhite
        265
    DeWhite  
       2019-12-17 10:39:01 +08:00
    团队作业肯定用 B,
    cominghome
        266
    cominghome  
       2019-12-17 10:41:45 +08:00
    看需求,AB 都有各自的使用场景,大部分时候倾向于 B (前端同学估计会 100%选 B 2333 )
    luoruiqing
        267
    luoruiqing  
       2019-12-17 10:46:54 +08:00
    选 B ! A 是 列表里一个元素?
    palmers
        268
    palmers  
       2019-12-17 10:47:13 +08:00
    我认为不存在对错, 将这两种数据结构放入具体的业务场景中 然后比较两种结构的优缺点个数就出来了
    HanMeiM
        269
    HanMeiM  
       2019-12-17 10:52:47 +08:00
    第一眼肯定是选 B
    但是具体情况下选 A 也没问题
    kedron
        270
    kedron  
       2019-12-17 10:54:39 +08:00
    @DOLLOR 前端会知道 192.168.1.2 和 192.168.1.1 这个两个 IP 吗?要是还有其他不同的很多个 IP 呢?
    nnnToTnnn
        271
    nnnToTnnn  
       2019-12-17 10:55:02 +08:00
    @mizzle #259 依据是什么,作为 JSON 的定义,key 可以是任何一个字符串,作为 JSON 而言,两种方式并没有任何区别,区别的仅仅只是后台所谓的 Class 后台的 Class 和 JSON 没有任何关系。

    不能因为大家解析 JSON 都是默认采用 Class 的字段名,所以认为 Class 必须和 JSON 字段对应吗?
    nnnToTnnn
        272
    nnnToTnnn  
       2019-12-17 10:58:00 +08:00
    所谓 Class 只不过有一个默认写好的 JSON 解析器帮你把 JSON 转换到了 Class 的实例,他能对应大多数的场景的一个通用的解决方案,当然还有部分场景无法覆盖的,一样可以重载一下,或者包装一下,都可以很好的解决这个问题。

    -----------------------------------------------

    问题的中心点不在于哪种格式,而是在于大家都采用一种格式,无论是 A 还是 B 确定一种就可以了,这样统一了,前后台都可以很好的包装一下解析器。或者写一个通用的解析方法
    zhouzm
        273
    zhouzm  
       2019-12-17 11:02:46 +08:00
    抛开 JSON 或 API 调用,原生开发里其实也有类型问题,接口开发中,返回对象集合到底采取数组形式还是键值对方式。
    * 合理的做法是应该返回数组,array.length 就能判断对象数量,array(index) 获取对象。
    但问题又来了,往往会出现对象有 name 属性,需要直接依据 name 方便的读写对象
    * 通常的做法是另外提供一个接口方法,根据 name 返回对象的 index。

    根据这个思路,其实 A 需求是存在的,但实现的方法应该是在 B 的基础上,再额外增加一个 key -> index 的键值对象做快速查询。
    no1xsyzy
        274
    no1xsyzy  
       2019-12-17 11:11:00 +08:00
    Twitter API 表示每个 Tweet 的时候用的是 A
    实际上是用来表示 “无限延续的部分列表” 的唯一途径
    no1xsyzy
        275
    no1xsyzy  
       2019-12-17 11:20:46 +08:00
    @codeismylife #11 不存在任何标准说 A 不行。
    @sagaxu #10 那么混杂一下:
    Map<String, Message>,message 带 ip 字段
    我可能上面有点说错了,Twitter 是这种(还包括事事参考 Twitter 的 Pocket )
    akakidz
        276
    akakidz  
       2019-12-17 11:25:15 +08:00
    作为一名前端,在没有特殊需求的情况下,都希望拿到的是 B
    MisakaMikoto
        277
    MisakaMikoto  
       2019-12-17 11:33:27 +08:00
    AB 都可以,如果是列表展示,显然 B。用 A 打死
    cquan
        278
    cquan  
       2019-12-17 11:36:45 +08:00
    我虽然也不是大牛,但我也觉得 b 比较容易理解
    codeismylife
        279
    codeismylife  
    OP
       2019-12-17 12:17:35 +08:00 via iPhone
    @yulgang 据 A 说,他见过 zabbix 里有这样的配置,所以他认为这么写没问题。
    TimLang
        280
    TimLang  
       2019-12-17 12:54:29 +08:00
    大多数不理解争论的人是没有碰到过不讲理的前端。。

    比如我们公司的前端小姐姐,最好一个接口把所有要的数据都放在里面,她才不管什么接口的规范呢。
    chenyu0532
        281
    chenyu0532  
       2019-12-17 12:56:43 +08:00
    测试用 A 正式用 B。。。这个吵啥。。。
    是不是活儿太少了。。。
    NoKey
        282
    NoKey  
       2019-12-17 12:59:02 +08:00
    A 通过页面给到 java 后台,java 后台如何自动解析?求大佬指导一下
    watzds
        283
    watzds  
       2019-12-17 13:02:44 +08:00 via Android
    A 的顺序没保证,A 能实现的 B 都能实现
    yuanfnadi
        284
    yuanfnadi  
       2019-12-17 13:20:00 +08:00
    interface ResponseA {
    [ip: string]: {
    Memory: string;
    HardDisk: string;
    };
    }

    interface ResponseB {
    ip: string;
    Memory: string;
    HardDisk: string;
    }

    const response: ResponseA = {
    '192.168.1.2': {
    Memory: '10%',
    HardDisk: '25',
    },
    '192.168.1.1': {
    Memory: '25%',
    HardDisk: '10',
    },
    };

    const responseb: ResponseB[] = Object.keys(response).map(ip => ({
    ...response[ip],
    ip,
    }));


    ts 有任何问题吗?
    mizzle
        285
    mizzle  
       2019-12-17 14:08:38 +08:00
    @nnnToTnnn 认为 B 更优的根据是作为 data exchange 格式, B 比 A 层级少, 且明确表示携带了数据的顺序信息.
    TimPeake
        286
    TimPeake  
       2019-12-17 14:10:38 +08:00
    之前我司有个 JAVA 经常写 A 现在坟头草已丈五 😉
    mtdhllf
        287
    mtdhllf  
       2019-12-17 14:12:29 +08:00
    安卓要是看到 A 写的想骂人~
    mht
        288
    mht  
       2019-12-17 14:12:52 +08:00
    写 js 客户端的话 A 没所谓

    写 java flutter 之类的客户端的话 B 会舒服很多
    yonoho
        289
    yonoho  
       2019-12-17 14:20:17 +08:00
    这么反驳:v2 网友几乎一致选择 B,这是民主决策
    duanxianze
        290
    duanxianze  
       2019-12-17 14:23:59 +08:00
    赞成 B
    yulgang
        291
    yulgang  
       2019-12-17 14:34:20 +08:00
    houzhimeng
        292
    houzhimeng  
       2019-12-17 14:35:20 +08:00
    这个是 b 了
    anyele
        293
    anyele  
       2019-12-17 14:59:52 +08:00 via Android
    你们是手动写代码解析的? 为啥还有不同的格式??
    xixixi
        294
    xixixi  
       2019-12-17 15:09:00 +08:00
    如果 ip 是不固定的,我选 B;
    如果 ip 是固定的,我也选 B,谁知道以后 ip 会不会增加
    tgich
        295
    tgich  
       2019-12-17 15:19:40 +08:00
    java8stream 分完组之后的结果就是 A 这样
    apaso
        296
    apaso  
       2019-12-17 15:29:13 +08:00 via iPhone
    能写整齐 b 的谁会用 a 估计有更深的业务要问下原因
    wqzjk393
        297
    wqzjk393  
       2019-12-17 15:50:54 +08:00
    @nnnToTnnn 之前学习的时候,我们老师说在代码里尽量不要出现对列表通过具体的一个序号进行索引,写的时候是爽了,维护起来能让人烦死
    onion83
        298
    onion83  
       2019-12-17 16:47:11 +08:00
    如果从使用方法上来看 A 比较优势,因为可以快速判断某个 key 在对象中是否存在, 而不需要遍历数组,前后端都可以。

    但是 A 有浏览器的兼容性问题,例如 ["0":"0","100":"100","a":"a"] 某些版本的浏览器会自动帮你填充为 : ["0":"0","1":NaN,"2":NaN ... "99":NaN ,"100":"100","a":"a"] 这个坑刚踩完。

    https://bugs.webkit.org/show_bug.cgi?id=170807
    abccccabc
        299
    abccccabc  
       2019-12-17 17:36:11 +08:00
    做接口的话,B,通用。

    除此以外,A。因为这种方式利于性能。因为不知道里面的 key 有多少个。
    a719114136
        300
    a719114136  
       2019-12-17 17:49:33 +08:00 via Android
    服务端用 A 省事,客户端用 B 省事
    1  2  3  4  
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1143 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 18:34 · PVG 02:34 · LAX 10:34 · JFK 13:34
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.