«

基于JS怎么将JSON数据转换为TypeScript类型声明的工具

时间:2024-7-17 16:57     作者:韩俊     分类: Javascript


这篇文章主要介绍“基于JS怎么将JSON数据转换为TypeScript类型声明的工具”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“基于JS怎么将JSON数据转换为TypeScript类型声明的工具”文章能帮助大家解决问题。

    一、实现的功能

      将 JSON 数据转换为 TypeScript 类型定义。

      支持嵌套的复杂类型,如数组和对象。

      支持自定义类型名称和命名空间。

      支持将转换后的 TypeScript 类型定义保存为文件。

    二、工具使用方法

    安装工具:

    npm install -g my-json-to-ts

    运行工具:

    my-json-to-ts input.json output.ts

    其中

    input.json
    是要转换的 JSON 文件路径,
    output.ts
    是转换后的 TypeScript 文件路径。

    --name 类型名称    # 指定转换后的类型名称,默认为 JsonType
    --namespace 命名空间 # 指定转换后的命名空间,默认为无
    --no-file          # 不将转换后的 TypeScript 类型定义保存为文件

    三、实现思路

      读取输入的 JSON 文件,解析成 JSON 对象。

      遍历 JSON 对象,根据不同的类型生成对应的 TypeScript 类型定义字符串。

      如果指定了类型名称和命名空间,则在生成的 TypeScript 类型定义字符串前面添加对应的声明。

      如果指定了保存文件,则将生成的 TypeScript 类型定义字符串写入文件。

    四、使用示例

    以下是将JSON 数据和转换后的 TypeScript 类型定义示例:

    简单的JSON 数据

    {
      "name": "John",
      "age": 30,
      "address": {
        "city": "New York",
        "state": "NY"
      },
      "hobbies": [
        "reading",
        "traveling"
      ]
    }

    输出对应简单的类型定义

    interface JsonType {
      name: string;
      age: number;
      address: {
        city: string;
        state: string;
      };
      hobbies: string[];
    }

    复杂的JSON 数据

    {
      "name": "John",
      "age": 30,
      "address": {
        "city": "New York",
        "state": "NY",
        "postalCode": 10001
      },
      "friends": [
        {
          "name": "Jane",
          "age": 28,
          "address": {
            "city": "Los Angeles",
            "state": "CA"
          }
        },
        {
          "name": "Bob",
          "age": 35,
          "address": {
            "city": "Chicago",
            "state": "IL"
          }
        }
      ],
      "hobbies": [
        "reading",
        "traveling",
        {
          "name": "swimming",
          "location": "pool"
        }
      ]
    }

    输出对应复杂类型定义

    interface JsonType {
      name: string;
      age: number;
      address: {
        city: string;
        state: string;
        postalCode: number;
      };
      friends: {
        name: string;
        age: number;
        address: {
          city: string;
          state: string;
        };
      }[];
      hobbies: (string | {
        name: string;
        location: string;
      })[];
    }

    五、具体实现代码

    首先引入两个 Node.js 模块:

    fs-extra
    commander
    fs-extra
    是一个简化了 Node.js 文件系统模块的封装,而
    commander
    是一个命令行工具的库,可以方便地解析命令行参数。

    接下来定义一个函数

    jsonToTs
    ,用于将 JSON 数据转换为 TypeScript 类型定义字符串。该函数采用递归的方式遍历 JSON 数据,生成对应的 TypeScript 类型定义。如果 JSON 数据是数组,则递归处理其中的每个元素;如果是对象,则递归处理其中的每个属性。最终,该函数返回一个 TypeScript 类型定义字符串。

    然后定义了两个异步函数,

    readJson
    writeTs
    ,分别用于读取 JSON 文件和将 TypeScript 类型定义字符串写入文件。

    最后定义一个名为

    jsonToTsFile
    的函数,该函数接收命令行参数并将其传递给
    jsonToTs
    函数,然后将生成的 TypeScript 类型定义字符串保存到文件中。如果命令行参数中指定了不保存文件,则该函数将直接将 TypeScript 类型定义字符串输出到控制台。

      const fs = require('fs-extra');
      const commander = require('commander');
    
      /**
       * 将 JSON 数据转换为 TypeScript 类型定义
       * @param {Object} object - 要转换的 JSON 对象
       * @param {string} [name=JsonType] - 转换后的类型名称
       * @param {string} [namespace] - 转换后的命名空间
       * @returns {string} - 转换后的 TypeScript 类型定义字符串
       */
      function jsonToTs(object, name = 'JsonType', namespace) {
          const getType = value => {
              let typeRes = ``;
              if (Array.isArray(value)) {
                  value.forEach(item => {
    
                      let subType = getType(item);
                      if (typeRes.split('|').indexOf(subType) < 0) {
                          typeRes += subType
                          typeRes += "|"
                      }
                  })
                  typeRes = typeRes.substring(0, typeRes.length - 1)
                  return `(${typeRes})[]`;
              }
              if (typeof value === 'object' && value !== null) {
                  const props = Object.entries(value)
                      .map(([key, val]) => `${key}: ${getType(val)}`)
                      .join('; ');
                  return `{ ${props} }`;
              }
              return typeof value;
          };
    
          const type = getType(object);
    
          const declaration = `interface ${name} ${type}`;
    
          return namespace ? `namespace ${namespace} { 
     ${declaration} 
    }` : declaration;
      }
    
      /**
       * 读取文件并解析成 JSON 对象
       * @param {string} path - 文件路径
       * @returns {Promise<Object>} - JSON 对象
       */
      async function readJson(path) {
          const content = await fs.readFile(path, 'utf8');
          return JSON.parse(content);
      }
    
      /**
       * 将 TypeScript 类型定义字符串写入文件
       * @param {string} content - TypeScript 类型定义字符串
       * @param {string} path - 文件路径
       * @returns {Promise<void>}
       */
      async function writeTs(content, path) {
          await fs.writeFile(path, content, 'utf8');
      }
    
      /**
       * 将 JSON 数据转换为 TypeScript 类型定义
       * @param {string} inputPath - 输入 JSON 文件路径
       * @param {string} outputPath - 输出 TypeScript 文件路径
       * @param {string} [options.name=JsonType] - 转换后的类型名称
       * @param {string} [options.namespace] - 转换后的命名空间
       * @param {boolean} [options.noFile] - 不将 TypeScript 类型定义保存为文件
       * @returns {Promise<void>}
       */
    
      async function jsonToTsFile(inputPath, outputPath, options) {
          const { name, namespace, noFile } = options
          try {
              const object = await readJson(inputPath);
              const type = jsonToTs(object, name, namespace);
              if (noFile) {
                  console.log(type);
              } else {
                  await writeTs(type, outputPath);
                  console.log(`Type definition saved to ${outputPath}`);
              }
          } catch (err) {
              console.error(err.message);
          }
      }
    
      const program = new commander.Command();
    
      program
          .arguments('<input> <output>')
          .option('--no-file', 'do not save to file')
          .option('-s, --namespace <namespace>', 'type namespace')
          .option('-n, --name <name>', 'type name', 'JsonType')
          .action(jsonToTsFile);
    
      program.parse(process.argv);

    标签: javascript

    热门推荐