V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
gamexg
V2EX  ›  问与答

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

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

    例如一个接口,能够收到登录、更改密码两种请求,收到的 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?
    cedoo22
        6
    cedoo22  
       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   ·   实用小工具   ·   1031 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 18:35 · PVG 02:35 · LAX 10:35 · JFK 13:35
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.