api-doc/swagger/parser.go

649 lines
24 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Package swagger ...
//
// Description : swagger ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2025-04-11 20:07
package swagger
import (
"errors"
"fmt"
apiDocDefine "git.zhangdeman.cn/gateway/api-doc/define"
"git.zhangdeman.cn/zhangdeman/consts"
"git.zhangdeman.cn/zhangdeman/wrapper"
"net/http"
"sort"
"strings"
)
// HandleOpenapiDocRes ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 18:00 2025/2/26
func HandleOpenapiDocRes(docRes *apiDocDefine.OpenapiDoc, ignoreApiTable map[string]bool, dataField string) ([]*apiDocDefine.ApiConfig, error) {
if nil == ignoreApiTable {
ignoreApiTable = make(map[string]bool)
}
hod := &handleOpenapiDoc{
docRes: docRes,
parseRes: make([]*apiDocDefine.ApiConfig, 0),
ignoreApiTable: ignoreApiTable,
dataField: dataField,
}
if err := hod.Parse(); nil != err {
return nil, err
}
return hod.parseRes, nil
}
type handleOpenapiDoc struct {
docRes *apiDocDefine.OpenapiDoc
parseRes []*apiDocDefine.ApiConfig
ignoreApiTable map[string]bool
dataField string
}
func (hod *handleOpenapiDoc) Parse() error {
// 排序, 保证输出顺序一致性
uriList := make([]string, 0)
for uri := range hod.docRes.Paths {
uriList = append(uriList, uri)
}
sort.Strings(uriList)
for _, uri := range uriList {
itemPath := hod.docRes.Paths[uri]
if err := hod.apiPathConfigToProjectConfig(uri, http.MethodGet, itemPath.Get); nil != err {
return err
}
if err := hod.apiPathConfigToProjectConfig(uri, http.MethodPut, itemPath.Put); nil != err {
return err
}
if err := hod.apiPathConfigToProjectConfig(uri, http.MethodPost, itemPath.Post); nil != err {
return err
}
if err := hod.apiPathConfigToProjectConfig(uri, http.MethodHead, itemPath.Head); nil != err {
return err
}
if err := hod.apiPathConfigToProjectConfig(uri, http.MethodPatch, itemPath.Patch); nil != err {
return err
}
if err := hod.apiPathConfigToProjectConfig(uri, http.MethodDelete, itemPath.Delete); nil != err {
return err
}
if err := hod.apiPathConfigToProjectConfig(uri, http.MethodConnect, itemPath.Connect); nil != err {
return err
}
if err := hod.apiPathConfigToProjectConfig(uri, http.MethodOptions, itemPath.Options); nil != err {
return err
}
if err := hod.apiPathConfigToProjectConfig(uri, http.MethodTrace, itemPath.Trace); nil != err {
return err
}
}
return nil
}
// apiPathConfigToProjectConfig 解析请求方法
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 18:48 2025/2/26
func (hod *handleOpenapiDoc) apiPathConfigToProjectConfig(uri string, method string, apiPathConfig *apiDocDefine.PathItemOperationConfig) error {
if hod.ignoreApiTable[fmt.Sprintf("%v_%v", strings.ToUpper(method), uri)] {
// 接口已存在
return nil
}
if apiPathConfig == nil {
return nil
}
requestContentTypeList := make([]string, 0)
if nil != apiPathConfig.RequestBody {
for contentType := range apiPathConfig.RequestBody.Content {
requestContentTypeList = append(requestContentTypeList, contentType)
}
}
if len(requestContentTypeList) == 0 {
requestContentTypeList = append(requestContentTypeList, consts.MimeTypeXWWWFormUrlencoded)
}
sort.Strings(requestContentTypeList)
tag := "未知分组"
if len(apiPathConfig.Tags) > 0 {
tag = apiPathConfig.Tags[0]
}
importUriConfig := &apiDocDefine.ApiConfig{
Tag: tag,
Name: apiPathConfig.Summary,
Uri: uri,
Method: strings.ToUpper(method),
ContentType: requestContentTypeList[0],
Description: apiPathConfig.Description,
ParamList: make([]*apiDocDefine.ApiParamItem, 0),
ResultList: make([]*apiDocDefine.ApiResultItem, 0),
}
// 解析公共的 Parameters , 任意请求方法都可能有 // TODO: 数组&对象递归处理
for _, itemParam := range apiPathConfig.Parameters {
importUriConfig.ParamList = append(importUriConfig.ParamList, &apiDocDefine.ApiParamItem{
Title: itemParam.Name,
Name: itemParam.Name,
Location: hod.openapiDocLocation2GatewayLocation(itemParam.In),
ParamType: hod.openapiDocType2GatewayType(fmt.Sprintf("%v", itemParam.Schema.Type), itemParam.Schema.Format),
IsRequired: itemParam.Required,
DefaultValue: "∂",
ExampleValue: "",
Description: itemParam.Description,
})
}
// post 类请求 body
if err := hod.handleRequestBody(importUriConfig, apiPathConfig.RequestBody, requestContentTypeList[0]); nil != err {
return err
}
// 处理response
if err := hod.handleResponseBody(importUriConfig, apiPathConfig.Responses); nil != err {
return err
}
// 解析response
hod.parseRes = append(hod.parseRes, importUriConfig)
return nil
}
// handleRequestBody 解析request body
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 12:17 2025/2/27
func (hod *handleOpenapiDoc) handleRequestBody(importUriConfig *apiDocDefine.ApiConfig, requestBodyData *apiDocDefine.RequestBody, selectRequestContentType string) error {
if nil == requestBodyData || nil == requestBodyData.Content {
return nil
}
if nil == requestBodyData.Content[selectRequestContentType] {
return fmt.Errorf("select content_type = %v is not found in requestBodyData.Content", selectRequestContentType)
}
requestBody := requestBodyData.Content[selectRequestContentType].Schema
if len(requestBody.Ref) == 0 {
return nil
}
requestBodyRequiredParamTable := map[string]bool{}
for _, itemParamName := range requestBody.Required {
requestBodyRequiredParamTable[itemParamName] = true
}
if len(requestBody.Ref) > 0 {
refCfg, err := hod.getResComponentsConfig(requestBody.Ref)
if nil != err {
return err
}
// ref 配置合并
if nil == requestBodyData.Content[selectRequestContentType].Schema.Properties {
requestBodyData.Content[selectRequestContentType].Schema.Properties = make(map[string]*apiDocDefine.Property)
}
for paramName, itemParam := range refCfg.Properties {
requestBodyData.Content[selectRequestContentType].Schema.Properties[paramName] = itemParam
}
for _, itemParamName := range refCfg.Required {
requestBodyRequiredParamTable[itemParamName] = true
}
}
for requestBodyParamName, requestBodyParamConfig := range requestBody.Properties {
// 对象、数组、引用递归解析
if err := hod.expendObjectOrArrayRequest(importUriConfig, requestBodyRequiredParamTable, "", "", requestBodyParamName, requestBodyParamConfig); nil != err {
return err
}
}
return nil
}
func (hod *handleOpenapiDoc) expendObjectOrArrayRequest(importUriConfig *apiDocDefine.ApiConfig, requestBodyRequiredParamTable map[string]bool, rootRef string, parentPath string, currentPropertyName string, currentProperty *apiDocDefine.Property) error {
if len(parentPath) > 0 {
currentPropertyName = parentPath + "." + currentPropertyName
}
defaultValue := wrapper.AnyDataType(currentProperty.Default).ToString().Value()
// 基础数据类型
if len(currentProperty.Properties) == 0 && currentProperty.Type != consts.SwaggerDataTypeObject && currentProperty.Type != consts.SwaggerDataTypeArray && len(currentProperty.Ref) == 0 {
importUriConfig.ParamList = append(importUriConfig.ParamList, &apiDocDefine.ApiParamItem{
Title: currentPropertyName,
Name: currentPropertyName,
Location: consts.RequestDataLocationBody.String(),
ParamType: hod.openapiDocType2GatewayType(fmt.Sprintf("%v", currentProperty.Type), currentProperty.Format),
IsRequired: requestBodyRequiredParamTable[currentPropertyName],
DefaultValue: defaultValue,
ExampleValue: "",
Description: currentProperty.Description,
})
return nil
}
// 处理数组(注意循环引用导致的递归死循环)
if currentProperty.Type == consts.SwaggerDataTypeArray {
if nil == currentProperty.Items {
if strings.HasSuffix(parentPath, ".[]") {
// 说明已经set过,不处理
return nil
}
importUriConfig.ParamList = append(importUriConfig.ParamList, &apiDocDefine.ApiParamItem{
Title: currentPropertyName,
Name: currentPropertyName,
Location: consts.RequestDataLocationBody.String(),
ParamType: consts.DataTypeSliceAny.String(),
IsRequired: requestBodyRequiredParamTable[currentPropertyName],
DefaultValue: "",
ExampleValue: "",
Description: currentProperty.Description,
})
return nil
}
// 数组类型, 如果是基础类型的数组, 直接返回, map 数组或嵌套数组层层展开
if currentProperty.Items.Type == consts.SwaggerDataTypeObject || currentProperty.Items.Type == consts.SwaggerDataTypeArray || len(currentProperty.Items.Ref) > 0 {
if !strings.HasSuffix(parentPath, ".[]") {
dataType := hod.openapiDocType2GatewayType(fmt.Sprintf("%v", currentProperty.Type), currentProperty.Format)
// 数组根key没设置过进行set
importUriConfig.ParamList = append(importUriConfig.ParamList, &apiDocDefine.ApiParamItem{
Title: currentPropertyName,
Name: currentPropertyName,
Location: consts.RequestDataLocationBody.String(),
ParamType: "[]" + dataType,
IsRequired: requestBodyRequiredParamTable[currentPropertyName],
DefaultValue: defaultValue,
ExampleValue: "",
Description: currentProperty.Description,
})
}
if len(currentProperty.Items.Ref) == 0 {
return nil
}
// 解析ref内容
refDefine, err := hod.getResComponentsConfig(currentProperty.Items.Ref)
if nil != err {
return err
}
if strings.Contains(rootRef, currentProperty.Items.Ref) {
dataType := consts.DataTypeAny.String()
// 循环引用
if refDefine.Type == consts.SwaggerDataTypeObject {
dataType = consts.DataTypeSliceMapStringAny.String()
} else if refDefine.Type == consts.SwaggerDataTypeArray {
dataType = consts.DataTypeSliceSlice.String()
}
importUriConfig.ParamList = append(importUriConfig.ParamList, &apiDocDefine.ApiParamItem{
Title: currentPropertyName,
Name: currentPropertyName,
Location: consts.RequestDataLocationBody.String(),
ParamType: dataType,
IsRequired: requestBodyRequiredParamTable[currentPropertyName],
DefaultValue: defaultValue,
ExampleValue: "",
Description: currentProperty.Description,
})
return nil
}
// 数组子项是数组或者对象
currentPropertyName = currentPropertyName + ".[]"
newRequiredTable := make(map[string]bool)
for _, item := range refDefine.Required {
newRequiredTable[item] = true
}
for itemName, itemVal := range refDefine.Properties {
if err = hod.expendObjectOrArrayRequest(importUriConfig, newRequiredTable, rootRef+currentProperty.Items.Ref, currentPropertyName, itemName, itemVal); nil != err {
return err
}
}
return nil
} else {
// 数组子项是基础类型
dataType := hod.openapiDocType2GatewayType(fmt.Sprintf("%v", currentProperty.Type), currentProperty.Format)
if len(currentProperty.Format) == 0 {
// 未指定format dataType 添加 [] 前缀
dataType = "[]" + dataType
}
importUriConfig.ParamList = append(importUriConfig.ParamList, &apiDocDefine.ApiParamItem{
Title: currentPropertyName,
Name: currentPropertyName,
Location: consts.RequestDataLocationBody.String(),
ParamType: dataType,
IsRequired: requestBodyRequiredParamTable[currentPropertyName],
DefaultValue: defaultValue,
ExampleValue: "",
Description: currentProperty.Description,
})
return nil
}
}
if currentProperty.Type == consts.SwaggerDataTypeObject && currentProperty.Ref == "" && len(currentProperty.Properties) == 0 {
// 对象类型, 且未设置引用类型, 并且属性也为空, 对应any数据类型
importUriConfig.ParamList = append(importUriConfig.ParamList, &apiDocDefine.ApiParamItem{
Title: currentPropertyName,
Name: currentPropertyName,
Location: consts.RequestDataLocationBody.String(),
ParamType: consts.DataTypeAny.String(),
IsRequired: requestBodyRequiredParamTable[currentPropertyName],
DefaultValue: defaultValue,
ExampleValue: "",
Description: currentProperty.Description,
})
return nil
}
// 遍历 Properties
for fieldName, fieldVal := range currentProperty.Properties {
importUriConfig.ParamList = append(importUriConfig.ParamList, &apiDocDefine.ApiParamItem{
Title: fieldName,
Name: fieldName,
Location: consts.RequestDataLocationBody.String(),
ParamType: hod.openapiDocType2GatewayType(fmt.Sprintf("%v", fieldVal.Type), fieldVal.Format),
IsRequired: requestBodyRequiredParamTable[currentPropertyName],
DefaultValue: defaultValue,
Description: fieldVal.Description,
})
// 对象或者数组, 深度递归
if fieldVal.Type == consts.SwaggerDataTypeObject || fieldVal.Type == consts.SwaggerDataTypeArray {
if err := hod.expendObjectOrArrayRequest(importUriConfig, requestBodyRequiredParamTable, rootRef, currentPropertyName, fieldName, fieldVal); nil != err {
return err
}
}
if len(fieldVal.Ref) > 0 {
// 引用的结构体定义, 递归解析
if propertyResDefine, err := hod.getResComponentsConfig(fieldVal.Ref); nil != err {
return err
} else {
newRequiredTable := make(map[string]bool)
for _, item := range propertyResDefine.Required {
newRequiredTable[item] = true
}
for _, itemProperty := range propertyResDefine.Properties {
if err = hod.expendObjectOrArrayRequest(importUriConfig, newRequiredTable, rootRef+fieldVal.Ref, currentPropertyName, fieldName, itemProperty); nil != err {
return err
}
}
}
}
}
return nil
}
// handleResponseBody 解析响应body
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 13:44 2025/2/27
func (hod *handleOpenapiDoc) handleResponseBody(importUriConfig *apiDocDefine.ApiConfig, requestBodyTable map[string]*apiDocDefine.Response) error {
if nil == requestBodyTable || nil == requestBodyTable["200"] {
return nil
}
if len(requestBodyTable["200"].Content) == 0 {
// 无返回值
return nil
}
contentTypeList := []string{}
for itemContentType := range requestBodyTable["200"].Content {
contentTypeList = append(contentTypeList, itemContentType)
}
if len(contentTypeList) == 0 {
contentTypeList = append(contentTypeList, consts.MimeTypeJson)
}
sort.Strings(contentTypeList)
selectResponseContentType := contentTypeList[0]
responseBodyData := requestBodyTable["200"].Content[selectResponseContentType].Schema
// 处理properties
if hod.dataField == "" {
// 未指定数据字段
for resultName, itemResult := range responseBodyData.Properties {
if err := hod.expendObjectOrArrayPath(importUriConfig, "", "", resultName, itemResult); nil != err {
return err
}
}
} else {
// 指定数据字段
fieldConfig := responseBodyData.Properties[hod.dataField]
if nil == fieldConfig {
return fmt.Errorf("data_field=%v 在相应body中不存在, uri=%v", hod.dataField, importUriConfig.Uri)
}
for fieldName, fieldVal := range fieldConfig.Properties {
// 引用的结构体定义, 递归解析
if err := hod.expendObjectOrArrayPath(importUriConfig, "", "", fieldName, fieldVal); nil != err {
return err
}
}
}
if len(responseBodyData.Ref) == 0 {
return nil
}
refCfg, err := hod.getResComponentsConfig(responseBodyData.Ref)
if nil != err {
return err
}
// ref 配置合并
for resultName, itemResult := range refCfg.Properties {
if err = hod.expendObjectOrArrayPath(importUriConfig, responseBodyData.Ref, "", resultName, itemResult); nil != err {
return err
}
}
return nil
}
// expendObjectOrArrayPath 展开ref对象路径
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:28 2025/4/8
func (hod *handleOpenapiDoc) expendObjectOrArrayPath(importUriConfig *apiDocDefine.ApiConfig, rootRef string, parentPath string, currentPropertyName string, currentProperty *apiDocDefine.Property) error {
if len(parentPath) > 0 {
currentPropertyName = parentPath + "." + currentPropertyName
}
defaultValue := wrapper.AnyDataType(currentProperty.Default).ToString().Value()
// 基础数据类型
if len(currentProperty.Properties) == 0 && currentProperty.Type != consts.SwaggerDataTypeObject && currentProperty.Type != consts.SwaggerDataTypeArray && len(currentProperty.Ref) == 0 {
importUriConfig.ResultList = append(importUriConfig.ResultList, &apiDocDefine.ApiResultItem{
Title: currentPropertyName,
DataPath: currentPropertyName,
DataLocation: consts.RequestDataLocationBody.String(),
DataType: hod.openapiDocType2GatewayType(fmt.Sprintf("%v", currentProperty.Type), currentProperty.Format),
DefaultValue: defaultValue,
ExampleValue: defaultValue,
Description: currentProperty.Description,
})
return nil
}
// 处理数组(注意循环引用导致的递归死循环)
if currentProperty.Type == consts.SwaggerDataTypeArray {
if nil == currentProperty.Items {
if strings.HasSuffix(parentPath, ".[]") {
// 说明已经set过,不处理
return nil
}
importUriConfig.ResultList = append(importUriConfig.ResultList, &apiDocDefine.ApiResultItem{
Title: currentPropertyName,
DataPath: currentPropertyName,
DataLocation: consts.ResponseDataLocationBody.String(),
DataType: consts.DataTypeSliceAny.String(),
DefaultValue: defaultValue,
ExampleValue: defaultValue,
Description: currentProperty.Description,
})
return nil
}
// 数组类型, 如果是基础类型的数组, 直接返回, map 数组或嵌套数组层层展开
if currentProperty.Items.Type == consts.SwaggerDataTypeObject || currentProperty.Items.Type == consts.SwaggerDataTypeArray || len(currentProperty.Items.Ref) > 0 {
if !strings.HasSuffix(parentPath, ".[]") {
// 数组根key没设置过进行set
importUriConfig.ResultList = append(importUriConfig.ResultList, &apiDocDefine.ApiResultItem{
Title: currentPropertyName,
DataPath: currentPropertyName,
DataLocation: consts.RequestDataLocationBody.String(),
DataType: consts.DataTypeSliceAny.String(),
DefaultValue: defaultValue,
ExampleValue: defaultValue,
Description: currentProperty.Description,
})
}
if len(currentProperty.Items.Ref) == 0 {
return nil
}
// 解析ref内容
refDefine, err := hod.getResComponentsConfig(currentProperty.Items.Ref)
if nil != err {
return err
}
if strings.Contains(rootRef, currentProperty.Items.Ref) {
dataType := consts.DataTypeAny.String()
// 循环引用
if refDefine.Type == consts.SwaggerDataTypeObject {
dataType = consts.DataTypeSliceMapStringAny.String()
} else if refDefine.Type == consts.SwaggerDataTypeArray {
dataType = consts.DataTypeSliceSlice.String()
}
importUriConfig.ResultList = append(importUriConfig.ResultList, &apiDocDefine.ApiResultItem{
Title: currentPropertyName,
DataPath: currentPropertyName,
DataLocation: consts.RequestDataLocationBody.String(),
DataType: dataType,
DefaultValue: defaultValue,
ExampleValue: defaultValue,
Description: currentProperty.Description,
})
return nil
}
// 数组子项是数组或者对象
currentPropertyName = currentPropertyName + ".[]"
for itemName, itemVal := range refDefine.Properties {
if err = hod.expendObjectOrArrayPath(importUriConfig, rootRef+currentProperty.Items.Ref, currentPropertyName, itemName, itemVal); nil != err {
return err
}
}
return nil
} else {
// 数组子项是基础类型
dataType := hod.openapiDocType2GatewayType(fmt.Sprintf("%v", currentProperty.Type), currentProperty.Format)
if len(currentProperty.Format) == 0 {
// 未指定format dataType 添加 [] 前缀
dataType = "[]" + dataType
}
importUriConfig.ResultList = append(importUriConfig.ResultList, &apiDocDefine.ApiResultItem{
Title: currentPropertyName,
DataPath: currentPropertyName,
DataLocation: consts.RequestDataLocationBody.String(),
DataType: dataType,
DefaultValue: defaultValue,
ExampleValue: defaultValue,
Description: currentProperty.Description,
})
return nil
}
}
if currentProperty.Type == consts.SwaggerDataTypeObject && currentProperty.Ref == "" && len(currentProperty.Properties) == 0 {
// 对象类型, 且未设置引用类型, 并且属性也为空, 对应any数据类型
importUriConfig.ResultList = append(importUriConfig.ResultList, &apiDocDefine.ApiResultItem{
Title: currentPropertyName,
DataPath: currentPropertyName,
DataLocation: consts.RequestDataLocationBody.String(),
DataType: consts.DataTypeAny.String(),
DefaultValue: defaultValue,
ExampleValue: defaultValue,
Description: currentProperty.Description,
})
return nil
}
// 遍历 Properties
for fieldName, fieldVal := range currentProperty.Properties {
importUriConfig.ResultList = append(importUriConfig.ResultList, &apiDocDefine.ApiResultItem{
Title: fieldName,
DataPath: fieldName,
DataLocation: consts.RequestDataLocationBody.String(),
DataType: hod.openapiDocType2GatewayType(fmt.Sprintf("%v", fieldVal.Type), fieldVal.Format),
Description: fieldVal.Description,
DefaultValue: defaultValue,
ExampleValue: defaultValue,
})
// 对象或者数组, 深度递归
if fieldVal.Type == consts.SwaggerDataTypeObject || fieldVal.Type == consts.SwaggerDataTypeArray {
if err := hod.expendObjectOrArrayPath(importUriConfig, rootRef, currentPropertyName, fieldName, fieldVal); nil != err {
return err
}
}
if len(fieldVal.Ref) > 0 {
// 引用的结构体定义, 递归解析
if propertyResDefine, err := hod.getResComponentsConfig(fieldVal.Ref); nil != err {
return err
} else {
for _, itemProperty := range propertyResDefine.Properties {
if err = hod.expendObjectOrArrayPath(importUriConfig, rootRef+fieldVal.Ref, currentPropertyName, fieldName, itemProperty); nil != err {
return err
}
}
}
}
}
return nil
}
// getResComponentsConfig 获取ref指向components的定义
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 11:17 2025/2/27
func (hod *handleOpenapiDoc) getResComponentsConfig(ref string) (*apiDocDefine.Schema, error) {
refKey := strings.TrimPrefix(ref, "#/components/schemas/")
if _, exist := hod.docRes.Components.Schemas[refKey]; exist {
return hod.docRes.Components.Schemas[refKey], nil
}
// apifox 导出的文档, ref 部分, 空格被转义, 但是 components 定义中空格未被转义
refKey = strings.ReplaceAll(refKey, "%20", " ")
if _, exist := hod.docRes.Components.Schemas[refKey]; exist {
return hod.docRes.Components.Schemas[refKey], nil
}
return nil, errors.New("components not found : " + refKey)
}
// openapiDocLocation2GatewayLocation 文档数据位置转为网关的数据位置
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 21:06 2025/2/26
func (hod *handleOpenapiDoc) openapiDocLocation2GatewayLocation(openapiDocLocation string) string {
openapiDocLocation = strings.ToUpper(openapiDocLocation)
for _, itemLocation := range consts.RequestDataLocationList {
if strings.ToUpper(itemLocation.Value.String()) == openapiDocLocation {
return itemLocation.Value.String()
}
}
// 没有明确配置参数位置query/header/cookie/body等, 会自动按照请求尝试获取
return consts.RequestDataLocationAny.String()
}
// openapiDocType2GatewayType 文档数据类型转为网关数据类型
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 21:07 2025/2/26
func (hod *handleOpenapiDoc) openapiDocType2GatewayType(openapiDocType string, formatType string) string {
openapiDocType = strings.ToLower(openapiDocType)
if formatType == "" {
formatType = openapiDocType
}
formatType = strings.ReplaceAll(strings.ReplaceAll(formatType, " ", ""), "interface{}", "any")
for _, itemType := range consts.DataTypeList {
if itemType.Value.String() == formatType {
return itemType.Value.String()
}
}
switch openapiDocType {
case consts.SwaggerDataTypeString:
return consts.DataTypeString.String()
case consts.SwaggerDataTypeInteger:
return consts.DataTypeInt.String()
case consts.SwaggerDataTypeNumber:
return consts.DataTypeFloat64.String()
case consts.SwaggerDataTypeArray:
return consts.DataTypeSliceAny.String()
case consts.SwaggerDataTypeObject:
return consts.DataTypeMapStrAny.String()
case consts.SwaggerDataTypeBoolean:
return consts.DataTypeBool.String()
}
// 兜底数据类型any
return consts.DataTypeAny.String()
}