首页 > 解决方案 > Swagger 定义解析为简化的 JS 对象(复杂对象操作)

问题描述

我正在尝试使用 TypeDoc、Swagger 和 SwaggerJsDoc 为我的项目构建一些文档。由于 TypeDoc 和 swagger 有不同的注解类型,而且 Swagger 的注解更加详细,我希望 TypeDoc 能够阅读我的 Swagger 注解。我已经设法利用 TypeDoc 的注释解析器,并成功地为我的代码和 API 创建了漂亮的自定义文档,例如:

使用 Typedoc 生成的文档

我对此非常满意,但是很难将 Swagger 的架构定义解析为纯 Javascript 对象以显示我的响应或正文示例。在我看来,Swaggers 的定义太复杂了。它们可以大大简化,同时保持相同的信息。他们是这样来的:

  {
    "type": "object",
    "properties": {
      "minStockProds": {
        "type": "array",
        "items": {
          "type": "object",
          "properties": {
            "sku": {
              "type": "string"
            },
            "minStock": {
              "type": "number"
            },
            "ref": {
              "type": "string"
            }
          }
        }
      },
      "ordersCount": {
        "type": "number"
      }
    }
  }

或者这个!,极端地说:

{
        "type": "object",
        "properties": {
          "test": {
            "type": "object",
            "properties": {
              "test1": {
                "type": "string"
              },
              "test2": {
                "type": "object",
                "properties": {
                  "test3": {
                    "type": "number"
                  },
                  "test4": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "test5": {
                          "type":"string"
                        },
                        "test6": {
                          "type": "number"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "test7": {
            "type":"array",
            "items":{
              "type": "object",
              "properties": {
                "name":{
                  "type": "string"
                },
                "value": {
                  "type": "number"
                }
              }
            }
          }
        }
      }

我怎么能把它解析成这个?

{
  minStockProds: [
    {
      sku: "string",
      minStock: "number",
      ref: "string"
    }
  ],
  ordersCount: "number",
}

或这个?

{
  test: {
    test1: "string",
    test2: {
      test3: "number",
      test4: [
        {
          test5: "string",
          test6: "number",
        }
      ]
    }
  },
  test7: [
    {
      name: "string",
      value: "number",
    }
  ]
}

我已经尝试了很多方法来适应所有这些类型的对象,以至于我的代码现在看起来很可怕而且在这里显示令人困惑,这将是一种阅读它的努力。

谁能给我一个提示或告诉一个可以为我提供便利的图书馆?无需完全解决此问题,只需寻找选项。我什至尝试查看 Swagger-UI 包以了解他们是如何做到的,但仍在寻找能够做到这一点的函数。

非常感谢!

标签: jsonparsingrecursionjavascript-objects

解决方案


经过大量的头撞墙后,我设法得到了这样的东西。一点都不漂亮,但它确实有效。我要把它贴在这里,因为我不希望任何人像我一样经历几天的反复试验。

function sanitizeObjectPropertyTypes(swaggerObj) {
  let copyObj = JSON.parse(JSON.stringify(swaggerObj));
  if(copyObj.$ref){
    copyObj = copyObj.$ref;
  } if (copyObj.description) {
    delete copyObj.description;
  }

  let parsedObj = {};

  function parse(obj, current) {
    let ikey;
    let value;
    for (key in obj) {
      if (obj.hasOwnProperty(key)) {
        value = obj[key];
        ikey = current ? `${current}.${key}` : key;
        if (typeof value === 'object') {
          parse(value, ikey);
        } else if (ikey !== 'type') {
          const path = ikey.replace(/(properties|\.properties|\.items|\.schema|\.type)/g, '').replace(/^\.*|\.*$/, '').replace('..', '.');
          lodash.set(parsedObj, path, obj[key]);
        }
      }
    }
  }

  function insertArray(obj) {
    function recurse(objRec) {
      const keys = Object.keys(objRec);
      for (let i = 0; i < keys.length; i++) {
        if (typeof objRec[keys[i]] === 'object') {
          if (objRec[keys[i]].type === 'array') {
            const path = getObjPathByKey({ obj, key: keys[i] })[0].replace(/(properties|\.properties|\.items|\.schema|\.type)/g, '').replace(/^\.*|\.*$/, '').replace('..', '.');
            const val = lodash.get(parsedObj, path);
            lodash.set(parsedObj, path, [val]);
          }
          recurse(objRec[keys[i]]);
        }
      }
    }
    recurse(obj);
    if (parsedObj.items) {
      parsedObj = [parsedObj.items];
    }
    if(parsedObj.schema){
      parsedObj = parsedObj.schema;
    }
  }
  parse(copyObj, '');
  insertArray(copyObj);

  return parsedObj;
}

推荐阅读