V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
chuanqirenwu
V2EX  ›  前端开发

有没有这种在运行时基于 typescript interface 信息序列化和反序列化 JSON 数据的库?

  •  
  •   chuanqirenwu · 2022-06-24 13:04:52 +08:00 · 1171 次点击
    这是一个创建于 663 天前的主题,其中的信息可能已经有所发展或是发生改变。

    提出此问题的场景:

    后端 API 返回 JSON 格式的数据,但字段通常都是 snake_case 的,即使是 camelCase ,有时候前端也需要对其重命名以符合前端的命名规范和一致性。

    通常后端 API 返回 JSON 格式的数据都是序列化为 JavaScript 后就丢弃了,目前的做法需要 2 步:

    1. 将后端 API 返回的数据 parse 为 JavaScript 对象(这一步通常框架会帮我们完成)
    2. 将原解析出来的对象 adapt 成前端需要的对象

    第 2 步中存在这么一些问题:

    • 从后端解析的原始对象,如果不为其定义一个 TypeScript interface ,无法智能提示,如果定义,则需要为后端返回的原始对象定义一个 interface ,同时还要为转换后的前端对象定义一个 interface ,这就存在 2 个长得很像的 interface ,大部分差异只在于字段的 case 风格。
    • 后端对象往前端对象转换时,存在 undefined 风险。这在转换的时候可能是检查不出来的,在后续运行使用某些字时可能触发异常。

    一种解决此问题的想法

    解决思路是允许后端对象和前端对象共享 1 个 interface ,并且除了静态检查,运行时也会校验数据合法性。

    举个例子,后端返回如下数据:

    	{
        "id": 1,
        "usename": "testuser",
        "avatar_url": "https://....",
        "is_admin": false,
        "type": "vip"
      }
    

    前端可以定义如下 interface:

    /*
    rename_all = "camelCase"
    */
    interface User {
      id: number;
      username: string;
      avatarUrl: string;
      isAdmin: string;
      /*
      alias="type"
      */
      userType: string;
    }
    

    注意到注释 rename_all = "camelCase",alias="type"(当然注释只是一种注解的形式,可行性暂不讨论),那么在根据这个 interface 序列化和反序列化是,库将根据注解将所有的 snake_case ,转为 camelCase ,userType 的值将从原数据对象的 type 字段提取。此外由于类型都是 string 或者 number ,如果原对象的值类型不符合,运行时将直接抛出异常。

    以下是一个调用示例:

    // 此调用内部会将后端返回的数据序根据 User interface 的信息列化为符合这个接口的对象,如果无法序列化,抛出异常。
    api.get("testuser").json<User>()
    
    5 条回复    2022-06-25 11:12:00 +08:00
    zcf0508
        1
    zcf0508  
       2022-06-24 13:13:43 +08:00
    浏览器运行的是 js 不是 ts
    iulo
        2
    iulo  
       2022-06-24 13:33:11 +08:00
    两个建议:
    1. 不要犯教条主义的错误,snake_case 和 camelCase 并不是绝对不能混用,只要明确好边界(返回的数据全部是 snake_case ,自身代码逻辑变量 camelCase ),没什么弊端,自己内部的规范应该是根据社区共识和自身情况来综合考虑的。
    2. 前后端使用通用协议描述数据结构,例如 pb ,你要做的是把协议文件"翻译"成一份类型描述放在项目内,而不是在运行时去下发类型描述。
    NathanInMac
        3
    NathanInMac  
       2022-06-24 13:38:43 +08:00
    x y 问题吧,楼上说的挺好的了。grpc web 之类的工具可以完美解决
    gfreezy
        4
    gfreezy  
       2022-06-24 13:55:04 +08:00   ❤️ 2
    看看这个 https://deepkit.io/
    iamgqb
        5
    iamgqb  
       2022-06-25 11:12:00 +08:00 via iPhone
    json mapper
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5939 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 02:27 · PVG 10:27 · LAX 19:27 · JFK 22:27
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.