支持私有云部署
AI知识库

53AI知识库

学习大模型的前沿技术与行业应用场景


旧文档swagger2.0转化为openapi格式方案

发布日期:2025-03-17 06:43:16 浏览次数: 1526 来源:三七互娱技术团队
推荐语

将Swagger2.0升级至OpenAPI 3.0,解决参数映射与文档描述分离问题。

核心内容:
1. Swagger2.0在项目中引发的问题及隐患
2. 旧文档描述与参数映射的调整方案
3. 路由方案的调整与适配器设计思路

杨芳贤
53A创始人/腾讯云(TVP)最具价值专家
01

背景

在以前的前台项目中,我们已经引入一套swagger2.0的语法准则,同时我们也定义了属于自己的一套返回数据结构。

但是swagger2.0的文档描述与参数映射赋值是分离开的,带来了两个问题:

开发过程中需要单独写注释文档描述

以下面内容为例子,分开描述会带来两个隐患:

隐患1、参数在文档中缺少描述,如下:game_id在实际是需要传的参数且需要进行处理包括表单验证等。但下面文档显然没有描述。

隐患2、同样的就算文档描述了,参数实际处理也未必接收game_id,这种不明确的文档描述对项目维护与前期对接都是一种挑战。

没有很好的规范我们的代码参数处理

参数接收与校验、传递都是通过独立key获取的,且每个项目与开发人员存在一定的操作差异

其实我们已经有了一套gf的参数赋值与验证规则,所以,本质上需要维持的是这套规则,兼容旧的路由注入方式。

如下:有了参数定义后,后续 文档描述生成、参数解析、参数验证、参数赋值 都依赖于参数定义,最后控制器拿到的也是根据参数定义设定的实际请求数据。

参数定义部分:

控制器处理部分:

同时因为有一个新项目开始开发,也开始在这套逻辑上探讨他的可行性。

02

路由方案

原先的路由方案

为了更加了解当前做的调整,我们先看下旧的路由方案。

最主要的核心代码有两个

第一 路由注入:将结构体+方法名解析为路由检索所需的key,绑定key与当前执行方法关系,留于后续供请求时检索路由对应的执行方法

StructA.MethodA1  →  [ "StructA::MethodA1" ] → func(StructA.MethodA1)

第二路由检索:将请求的path,切割后两位转化为结构体名+方法名,从而检索到对应对应的方法。

api/structA/methodA1  →  [ "StructA::MethodA1" ] → func(StructA.MethodA1)

调整方案

在维持路由检索不变的情况下(因为已经注入了一个全局路由处理的handel),我们能否再这个路由处理规则下转化为gf2的路由规范呢?

这里的想法是再外层增加一层适配器,他提供两个作用:

a、兼容原先路由解析处理方法,将 func (c *cXXX)XXX(ctx context.Context, req XXXXXReq) (XXXXXRes, error) 格式转化为 func (a *XXX) XXX(base *api_server_base.Base, arguments ...interface{}) error 方法格式

重点可以看 baseFunc 这里,解析到这个方法的格式符合 func (c *cXXX)XXX(ctx context.Context, req XXXXXReq) (XXXXXRes, error) 的格式,那么在这个方法的外围包装一层baseFunc方法,适应上面这里第二路由检索的统一处理封装。

b、预生成文档所需的结构内容

这里预生成了一个 goai.AddInput 结构体。完成了上面路由注入与处理兼容,我们只是让请求可以找到对应的处理方法,但是依然没有解决的问题是,文档生成要如何让gf通过读取指定的结构体。

这里先解释一下gf框架是怎么去将bind的Struct转化为对应的openapi的json的。我们先看当我们请求 127.0.0.1:8100/api.json 接口时发生了什么

第一步:路由器去找对应的openapiSpec方法,然后这个方法做的事情也很简单,将openapi变量去转化为json就结束了

那么对于我们的关注点来讲,是不是只要知道openapi这个变量是什么时候被填充数据,怎么被填充的就可以了

第二步:我们找到对应加入openapi的方法,幸运的是跟我们猜想的一样,这里也很简单,他会通过判断in的类型如果为func,就认为是通过func (c *cXXX)XXX(ctx context.Context, req XXXXXReq) (XXXXXRes, error)格式注入的路由,则后续会按这个格式解析到req跟res的结构体,从而补全请求入参与出参。那么我们要做的事情就简单很多了,我们只需要通过解析 func (c *cXXX)XXX(ctx context.Context, req XXXXXReq) (XXXXXRes, error) 转化为对应 AddInput就行了。这里抓包查看下 AddInput的格式就知道了。

其中

path是路由“/StructName/MethorName”;

prefix一般没有先不管;

Method:“POST/GET”;

Object:对应的func:func (c *cXXX)XXX(ctx context.Context, req XXXXXReq) (XXXXXRes, error)

显然,前面路由注入的方法里我们已经拿到了 func,反射解析出 req对应的结构体,再从结构体的g.Meta标签中取出path与Method就行

具体代码如下:

03

效果展示

控制器逻辑

参数处理与文档描述

测试与本地服务启动开放api.json接口

文档效果

至此,我们就完成了gf2与旧版base路由的统一,同样的其他项目通过简单改写路由注入方法,也可以实现同样的效果。

END


53AI,企业落地大模型首选服务商

产品:场景落地咨询+大模型应用平台+行业解决方案

承诺:免费场景POC验证,效果验证后签署服务协议。零风险落地应用大模型,已交付160+中大型企业

联系我们

售前咨询
186 6662 7370
预约演示
185 8882 0121

微信扫码

添加专属顾问

回到顶部

加载中...

扫码咨询