You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在Swagger中创建共享模型的多API并控制属性可见性

当然可以!我帮你设计一套既符合需求又易于维护的Swagger方案,完美实现公共/私有API的共享定义和字段权限控制。

方案概述

核心思路是把公共的模型、路径定义抽离到单独的共享文件中,让两个API文档通过$ref引用共享内容,同时在私有API中扩展模型来添加仅内部可见的字段。这样既避免了重复代码,又能精准控制不同API的字段可见范围。


1. 创建共享组件文件

先新建一个swagger-shared-components.json,存放公共的模型和路径基础定义:

{
  "components": {
    "schemas": {
      "BaseUser": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "用户公开名称"
          }
        },
        "required": ["name"]
      }
    },
    "paths": {
      "/users": {
        "get": {
          "summary": "获取用户列表",
          "tags": ["用户管理"],
          "parameters": [
            {
              "name": "page",
              "in": "query",
              "type": "integer",
              "description": "页码"
            }
          ]
        }
      }
    }
  }
}

2. 编写公共API文档(/api/v1/public)

新建swagger-public-v1.json,直接引用共享组件的公共模型和路径,只暴露公开字段:

{
  "openapi": "3.0.3",
  "info": {
    "title": "Public API v1",
    "version": "1.0.0",
    "description": "对外公开的API接口集合"
  },
  "servers": [
    {
      "url": "/api/v1/public"
    }
  ],
  "components": {
    "schemas": {
      "User": {
        "$ref": "./swagger-shared-components.json#/components/schemas/BaseUser"
      }
    }
  },
  "paths": {
    "/users": {
      "$ref": "./swagger-shared-components.json#/components/paths/users",
      "get": {
        "$ref": "./swagger-shared-components.json#/components/paths/users/get",
        "responses": {
          "200": {
            "description": "成功获取公开用户列表",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": { "$ref": "#/components/schemas/User" }
                }
              }
            }
          }
        }
      }
    }
  }
}

3. 编写私有API文档(/api/v1/private)

新建swagger-private-v1.json,引用共享组件后扩展模型,添加内部可见字段:

{
  "openapi": "3.0.3",
  "info": {
    "title": "Private API v1",
    "version": "1.0.0",
    "description": "内部专用API接口集合"
  },
  "servers": [
    {
      "url": "/api/v1/private"
    }
  ],
  "components": {
    "schemas": {
      "User": {
        "allOf": [
          { "$ref": "./swagger-shared-components.json#/components/schemas/BaseUser" },
          {
            "type": "object",
            "properties": {
              "some_internal_id": {
                "type": "string",
                "description": "内部用户唯一标识,仅私有API可见"
              }
            },
            "required": ["some_internal_id"]
          }
        ]
      }
    }
  },
  "paths": {
    "/users": {
      "$ref": "./swagger-shared-components.json#/components/paths/users",
      "get": {
        "$ref": "./swagger-shared-components.json#/components/paths/users/get",
        "responses": {
          "200": {
            "description": "成功获取含内部标识的用户列表",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": { "$ref": "#/components/schemas/User" }
                }
              }
            }
          }
        }
      }
    }
  }
}

4. 关键实现细节说明

  • 共享定义复用:通过$ref引用共享组件文件,公共和私有API的基础路径、公共模型完全同步,修改共享文件即可统一更新,避免重复维护。
  • 字段可见性控制
    • 公共API的User模型直接复用BaseUser,仅包含name字段。
    • 私有API的User模型用allOf组合BaseUser和新增的some_internal_id字段,实现“继承+扩展”的效果,确保内部字段只在私有文档中显示。
  • 路径扩展:私有API可以在引用共享路径的基础上,自定义响应内容(比如补充内部字段的返回结构),不影响公共API的定义。

5. Swagger UI加载配置(可选)

如果需要在Swagger UI中同时展示两个API,可以在UI配置中添加多个文档源:

window.onload = function() {
  const ui = SwaggerUIBundle({
    urls: [
      { url: "/swagger-public-v1.json", name: "Public API v1" },
      { url: "/swagger-private-v1.json", name: "Private API v1" }
    ],
    dom_id: '#swagger-ui',
    deepLinking: true,
    presets: [
      SwaggerUIBundle.presets.apis,
      SwaggerUIStandalonePreset
    ]
  });
};

注意事项

  1. 确保$ref的相对路径与实际部署的文件位置一致,避免引用失败。
  2. 文档层面的字段控制只是展示用,后端代码必须同步做权限校验,防止公共接口意外返回内部数据。
  3. 若需要共享更多控制器逻辑,可以把基础的请求参数、响应结构都放到共享组件中。

内容的提问来源于stack exchange,提问作者800c25d6-cd74-11ed-afa1-0242ac

火山引擎 最新活动