需求分析
swagger的api文档数据都是按照的固定的格式处理的,这个我们可以通过swagger的请求或者json文件可以看到。

对应的文档接口也就是这边数据中的paths中的数据。
从文档中我们可以看到相同的请求地址,会分成不同的请求方式列出,而paths中相同的请求地址只显示了一条。不着急,我们点开某一条链接看看他的数据。
可以清楚的看到所有的请求方式都包含在其中了,甚至备注,请求参数都在其中。
可见文档的所有的数据都是从改请求数据中获取整理的,那么我们的api文件也完全可以根据这份请求数据来生成。
实践
首先我们需要利用node获取到这份数据,使用request模块发起请求获取数据。
request(`${process.env.SWAGGER_API_JSON}`, (error, response) => {const result = JSON.parse(response.body) //result就是请求返回的数据})
剩下就是整理到获取的json数据。我们最终生成的api文件需要像swaagger页面上显示的那样,相同类别的接口都存放在一个文件中,并且以类别命名。
首先遍历paths数据
Object.keys(result.paths).forEach(item => {const app = item.replace(/\//, '').split('/') //首先根据/分割取处理每个pathconst api = app[0] //一般接口都是跟地址不同来区分是否相同类别的接口。比如企业相关的都是/ent/...if (!apiList[api]) { //这边就以第一段path左右key来整理所有的path数据,相同根path的都收集为一类apiList[api] = []}apiList[api].push(item)})
接下来处理初次整理完的数据
Object.keys(apiList).forEach(item => {const tempApiList = apiList[item].slice(0) //浅拷贝每一类接口集数据tempApiList.forEach(suItem => {suItem = (result.basePath === '/' ? '' : result.basePath) + suItem.split('/').filter(sss => !/{(.*?)}/g.test(sss)).join('/')}) //处理一遍不符合规范的数据let resultContent = `import request from '@/utils/request'`const methods = []const currentApis = apiList[item] //生成的文件需要根据类别分类,所以使用整理的数据遍历currentApis.forEach(key => {//原始的数据任然是在paths中,所以需要根据整理的收集集合去原始数据中获取对应的path数据Object.keys(result.paths[key]).forEach(type => {const method = result.paths[key][type] //获取请求详情数据let params = [] //整理请求参数if (key.match(/{(.*?)}/, '$1')) {const matchedParams = key.match(/{(.*?)}/g) || []params = params.concat(matchedParams.map(item => item.replace(/{(.*?)}/g, '$1')))}const name = toUpCase(key) //格式化命名,以驼峰方式命名resultContent += createMethod(name, key, type, method.parameters, params, method.summary)const uniqueName = name + type.toUpperCase() 命名拼接上请求方式名,用于区别相同请求path的不同请求类型methods.push(uniqueName)})})resultContent += `export {${methods.join(',')}}`try {resultContent = formatJson(resultContent) //格式化文本} catch (e) {// todo}const path = `${prefix}${result.basePath}/${item}.js` //存储路径checkDir(path) //检查写出的文本路径是否存在,不存在则直接创建路径fs.writeFileSync(path, resultContent) //写出// console.log('`${prefix}${result.basePath}/${item}.js`', `${prefix}${result.basePath}/${item}.js`)})
具体的请求方法体文本生成主要就是使用的createMethod函数
const createMethod = (name, url, method, params = [], paramKeys, summary) => {const uniqueName = name + method.toUpperCase()const comment = []//生成注释部分params.forEach(param => {comment.push(`@${param.name} ${param.type} ${param.description}`)})let tempUrl = `'${url}'`//传参if (paramKeys.length) {tempUrl = [tempUrl, '+', '`', paramKeys.map(item => ['/${', item, '}'].join('')).join(''), '`'].join('')}const _params = params.filter(item => item.in !== 'path')const paramPlaceholder = _params.length ? `${paramKeys.length ? ',' : ''} params` : ''const commentContent = !comment.length ? '' : ` /*** ${summary || ''}${comment.map(item => `* ${item}`).join('\n')}*/`return `${commentContent}const ${uniqueName} = async (${paramKeys.join(',')} ${paramPlaceholder}) => {return request({url: ${tempUrl},method: '${method}'${method === 'get' ? paramPlaceholder ? ',params' : '' : paramPlaceholder ? `,data: params` : ''}, //get和其他请求的参数处理})}`}
以上就基本完成了swagger的api文件的生成,剩下通过node的配置来把部分公共的变量独立出来,通过方便的修改配置来实现不同场景的使用
根目录的.env文件SWAGGER_API_JSON=http://... //api请求地址API_PREFIX=./src //生成的文件存储的根目录REQUEST_URL=@/utils/request //api文件中的ajax函数的引用路径
上面完成之后就可以直接node运行程序生成api文件了。
生成完的样例展示
