From 998c1613e44a17836da32571e302eeefe976fdbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E8=8C=B6=E6=B8=85=E6=AC=A2?= Date: Wed, 19 Feb 2025 15:35:47 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=AF=B9any=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E7=B1=BB=E5=9E=8B=E8=A7=A3=E6=9E=90=E7=9A=84=E6=94=AF?= =?UTF-8?q?=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- define/openapi.go | 2 ++ generate.go | 83 +++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 79 insertions(+), 6 deletions(-) diff --git a/define/openapi.go b/define/openapi.go index 9bf93d8..ca06663 100644 --- a/define/openapi.go +++ b/define/openapi.go @@ -133,6 +133,7 @@ type Schema struct { XEnumDescription map[string]string `json:"x-enumDescriptions,omitempty"` // 枚举值描述的扩展, redoc-free支持 Type string `json:"type,omitempty"` // 类型 Items *PropertyXOf `json:"items,omitempty"` // items 必须存在如果 type 的值是 array。 + OneOf []*PropertyXOf `json:"oneOf,omitempty"` // type 是一个对象, allOf 指向对象描述 Ref string `json:"$ref,omitempty"` // 类型引用 Format string `json:"format,omitempty"` // 格式化类型 Maximum *int64 `json:"maximum,omitempty"` // 最大值 @@ -174,6 +175,7 @@ type PropertyXOf struct { Maximum *int64 `json:"maximum,omitempty"` // 最大值 Minimum *int64 `json:"minimum,omitempty"` // 最小值 Ref string `json:"$ref,omitempty"` // 引用的结构描述 + // Items *PropertyXOf `json:"items,omitempty"` // 数据每一项已用类型 } // SchemaDiscriminator 当一个 request bodies 或 response payloads 可以是多种 schemas 时,可以使用一个 discriminator 对象来帮助序列化、反序列化和校验 diff --git a/generate.go b/generate.go index 52072a1..fc9f10c 100644 --- a/generate.go +++ b/generate.go @@ -369,6 +369,22 @@ func (g *Generate) ParseReadConfigParam(requestCfg *define.UriBaseConfig, baseRe }) continue } + if inputType.Field(i).Type.Kind() == reflect.Interface { + baseReqCfg.Parameters = append(baseReqCfg.Parameters, &define.PathConfigParameter{ + Name: ParseStructFieldTag.GetParamName(inputType.Field(i)), + In: consts.SwaggerParameterInQuery, + Description: ParseStructFieldTag.GetParamDesc(inputType.Field(i)), + Required: ValidateRule.IsRequired(inputType.Field(i)), + Deprecated: ParseStructFieldTag.Deprecated(inputType.Field(i)), + Schema: &define.Schema{ + OneOf: g.anyTypeConfig(inputType.Field(i)).OneOf, + Format: realInputTypeFormat, + Enum: ValidateRule.Enum(inputType.Field(i)), + XEnumDescription: ParseStructFieldTag.EnumDescription(inputType.Field(i)), + }, + }) + continue + } if inputType.Field(i).Type.Kind() == reflect.Ptr { // 处理指针 if inputType.Field(i).Type.Elem().Kind() == reflect.Struct { @@ -513,12 +529,18 @@ func (g *Generate) AddComponentsSchema(rootSchemaName string, pkgPath string, in g.handleAnonymousField(schemaName, inputType.Field(i)) continue } + if inputType.Kind() == reflect.Interface { + // 处理interface{}类型参数 + g.docData.Components.Schemas[schemaName].Properties[propertyName] = g.anyTypeConfig(inputType.Field(i)) + continue + } if inputType.Field(i).Type.Kind() == reflect.Ptr { // 处理指针 if inputType.Field(i).Type.Elem().Kind() == reflect.Struct { // 结构体指针 schemaNameNext := g.AddComponentsSchema(schemaName, propertyName, inputType.Field(i).Type.Elem()) g.docData.Components.Schemas[schemaName].Properties[propertyName] = &define.Property{ + // Description: ParseStructFieldTag.GetParamDesc(inputType.Field(i)), Ref: g.getSchemaRef(schemaNameNext), } } else { @@ -572,12 +594,16 @@ func (g *Generate) AddComponentsSchema(rootSchemaName string, pkgPath string, in g.AddComponentsSchema(schemaName, propertyName, inputType.Field(i).Type) } } else { - convertBaseType, _ := g.realBaseType2SwaggerType(inputType.Field(i).Type.String()) - g.docData.Components.Schemas[schemaName].Properties[propertyName] = &define.Property{ - Type: convertBaseType, - Format: inputType.Field(i).Type.String(), - Default: ParseStructFieldTag.GetDefaultValue(inputType.Field(i)), - Description: ParseStructFieldTag.GetParamDesc(inputType.Field(i)), + if inputType.Field(i).Type.Kind() == reflect.Interface { + g.docData.Components.Schemas[schemaName].Properties[propertyName] = g.anyTypeConfig(inputType.Field(i)) + } else { + convertBaseType, _ := g.realBaseType2SwaggerType(inputType.Field(i).Type.String()) + g.docData.Components.Schemas[schemaName].Properties[propertyName] = &define.Property{ + Type: convertBaseType, + Format: inputType.Field(i).Type.String(), + Default: ParseStructFieldTag.GetDefaultValue(inputType.Field(i)), + Description: ParseStructFieldTag.GetParamDesc(inputType.Field(i)), + } } } // 设置参数各种属性 @@ -625,6 +651,10 @@ func (g *Generate) handleAnonymousField(schemaName string, field reflect.StructF } else { baseConvertType, isBaseType := g.realBaseType2SwaggerType(itemField.Type.String()) if !isBaseType { + paramName := ParseStructFieldTag.GetParamName(itemField) + if itemField.Type.Kind() == reflect.Interface { + g.docData.Components.Schemas[schemaName].Properties[paramName] = g.anyTypeConfig(itemField) + } g.AddComponentsSchema(schemaName, handleType.Field(i).Type.PkgPath(), handleType.Field(i).Type) continue } else { @@ -814,3 +844,44 @@ func (g *Generate) parseBaseUriConfig(uriPrefix string, paramType reflect.Type) } return res, nil } + +// anyTypeConfig 任意类型数据配置 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 14:33 2025/2/19 +func (g *Generate) anyTypeConfig(structField reflect.StructField) *define.Property { + return &define.Property{ + Description: ParseStructFieldTag.GetParamDesc(structField), + OneOf: []*define.PropertyXOf{ + { + Type: consts.SwaggerDataTypeObject, + Format: "map[string]any", + }, + /* { + Type: consts.SwaggerDataTypeArray, + Format: "[]any", + Items: &define.PropertyXOf{ + Items: nil, + }, + },*/ + { + Type: consts.SwaggerDataTypeInteger, + Format: "int/uint", + }, + { + Type: consts.SwaggerDataTypeNumber, + Format: "int/uint/float", + }, + { + Type: consts.SwaggerDataTypeString, + Format: "string", + }, + { + Type: consts.SwaggerDataTypeBoolean, + Format: "bool", + }, + }, + } + +}