请教下,静态类型语言单个接口可以接收多种结构 json 序列化后的数据,怎么处理比较好? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
gamexg
V2EX    问与答

请教下,静态类型语言单个接口可以接收多种结构 json 序列化后的数据,怎么处理比较好?

  •  
  •   gamexg 2020-05-07 14:01:50 +08:00 1233 次点击
    这是一个创建于 2066 天前的主题,其中的信息可能已经有所发展或是发生改变。

    例如一个接口,能够收到登录、更改密码两种请求,收到的 json 结构如下:

    { "t":"l", //登录 "username":"name1", "password":"pass1" } 或 { "t":"cp", // 更改密码 "username":"name1", "oldpass":"oldpass", "newpass":"newpass" } 

    在未反序列化之前后端无法知道数据属于哪个结构,只能直接反序列化到通用 map 或者先反序列化一次获得类型 t 的值,然后再次解析到具体结构。

    但是这两个方案都有些小问题,静态语言下,map 通用结构使用不方便;两次反序列化方案浪费 cpu 资源。

    原来是尽可能的使用不同的接口处理不同结构的数据,tcp 连接等二进制协议则自定义包头来区分,一直没什么大问题。

    但是最近在处理 websocket 大量消息,就不太好用了。不可能每个结构使用一个独立的 websocket 连接,而常用的二进制协议包头方案也因为 web 前端不太方便不能使用(我不是专业前端,可能会有误解)。

    那么对于这种情况,静态类型语言后端怎么处理比较好?

    目前我这里的方案是,固定成为类似这样的结构:

    { "t":"?", "login":{ "username":"user1", "password":"pass1", }, "changepassword":{ "username":"name1", "oldpass":"oldpass", "newpass":"newpass" } } 

    login 时 login 字段有值,changepassword 为 null 的方式工作。请教下,还有其他更好的方案吗?

    8 条回复    2020-05-13 14:20:26 +08:00
    wysnylc
        1
    wysnylc  
       2020-05-07 14:45:04 +08:00   1
    加个字段声明请求内容是约定的什么结构
    optional
        2
    optional  
       2020-05-07 15:25:29 +08:00   2
    Java 里 jackson subtype 可以直接吐出来
    DGideas
        3
    DGideas  
       2020-05-07 15:29:23 +08:00   1
    @wysnylc 这样的话,其实数据中的 t 已经可以代表了。

    @gamexg 我一开始的思路也是像你说的“先反序列化一次获得类型 t 的值,然后再次解析到具体结构。”,期待其他大佬有更好的解决方案。
    teawithlife
        4
    teawithlife  
       2020-05-07 16:04:38 +08:00   1
    我能想到的有两个办法:
    1. 增加包头,不一定是二进制的包头,只要定长就可以了,前端应该很好实现。而且前端处理二进制也是没问题的,有对应的库
    2. 固定一个字段做匹配,比如要求有个"__type__"字段,用来表示结构体格式,然后先用 substring 一类的函数,把这段内容提取出来解析,确定了格式之后,就按对应的格式解析。
    HuHui
        5
    HuHui  
       2020-05-07 16:08:57 +08:00 via Android   1
    JSON-RPC?
    dr1q65MfKFKHnJr6
        6
    dr1q65MfKFKHnJr6  
       2020-05-07 16:17:53 +08:00   1
    貌似 现在用的这个 就是最优解了
    gamexg
        7
    gamexg  
    OP
       2020-05-13 11:55:16 +08:00
    @wysnylc #1 目前用 t 表示的类型,小缺陷是需要反序列化两次,或者一个结构包含所有的请求体。

    @optional #2 这个没用过,看起来是 json 库本身的功能?

    @teawithlife #4 包头是一个方案。substring 方案需要约定请求内不能出现其他 __type__ 字段,并且要求必须是固定格式,不能多出空格等,限制大了些。

    @HuHui #5 用现成的协议也是个选择。
    wysnylc
        8
    wysnylc  
       2020-05-13 14:20:26 +08:00
    @gamexg #7 t 可以独立成另一个接口参数或者写在 header 中
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     778 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 23ms UTC 20:11 PVG 04:11 LAX 12:11 JFK 15:11
    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