增加示例值解析 + 优化schema属性配置

This commit is contained in:
白茶清欢 2025-02-20 16:22:23 +08:00
parent bd7f6d2cfd
commit d7cbf81799
4 changed files with 65 additions and 59 deletions

View File

@ -155,6 +155,7 @@ type Property struct {
XEnumDescription map[string]string `json:"x-enumDescriptions,omitempty"` // 枚举值描述的扩展, redoc-free支持
Default any `json:"default,omitempty"` // 默认值 : 不同于 JSON Schema这个值必须符合定义与相同级别的 Schema 对象 中定义的类型,比如 type 是 string那么 default 可以是 "foo" 但不能是 1。
Description string `json:"description,omitempty"` // 数据描述, CommonMark syntax可以被用来呈现富文本格式.
Example string `json:"example,omitempty"` // 媒体类型的示例。示例对象应该符合此媒体类型的格式, 这里指定的example对象 object is mutually exclusive of the examples object. 而且如果引用的schema也包含示例在这里指定的example值将会覆盖schema提供的示例。
Maximum *int64 `json:"maximum,omitempty"` // 最大值
Minimum *int64 `json:"minimum,omitempty"` // 最小值
MinLength *int64 `json:"minLength,omitempty"` // 字符串最小长度

View File

@ -29,6 +29,8 @@ const (
TagUriTag = "tag" // 接口的tag
TagOutputStrict = "output_strict" // 接口数据是否为严格模式 : 严格模式, 响应数据必须是结构体/map非严格模式返回任意值
TagErrMsg = "err" // 验证失败错误信息tag
TagExample = "example" // 示例值
TagEg = "eg" // 示例值
TagContentType = "content_type"
TagOutputContentType = "output_content_type"
TagNameOmitempty = "omitempty"

View File

@ -342,13 +342,8 @@ func (g *Generate) ParseReadConfigParam(requestCfg *define.UriBaseConfig, baseRe
convertBaseType, isBaseType := g.realBaseType2SwaggerType(inputType.Field(i).Type.String())
realInputTypeFormat := inputType.Field(i).Type.String()
fieldType := inputType.Field(i).Type
/*if inputType.Field(i).Type.Kind() == reflect.Ptr {
fieldType = inputType.Field(i).Type.Elem()
}*/
if isBaseType {
// 当做默认基础类型, 默认不会出现 *map *[]
minVal := ValidateRule.Minimum(inputType.Field(i))
maxVal := ValidateRule.Maximum(inputType.Field(i))
itemParam := &define.PathConfigParameter{
Name: propertyName,
In: consts.SwaggerParameterInQuery,
@ -358,22 +353,13 @@ func (g *Generate) ParseReadConfigParam(requestCfg *define.UriBaseConfig, baseRe
Schema: &define.Schema{
Type: convertBaseType,
Format: realInputTypeFormat,
Default: ParseStructFieldTag.GetDefaultValue(inputType.Field(i)),
Enum: ValidateRule.Enum(inputType.Field(i)),
XEnumDescription: ParseStructFieldTag.EnumDescription(inputType.Field(i)),
},
AllowEmptyValue: false,
Style: "",
Explode: false,
AllowReserved: false,
}
if itemParam.Schema.Type == consts.SwaggerDataTypeString {
itemParam.Schema.MinLength = minVal
itemParam.Schema.MaxLength = maxVal
} else {
itemParam.Schema.Minimum = minVal
itemParam.Schema.Maximum = maxVal
}
g.setStructFieldProperty(itemParam.Schema, inputType.Field(i))
baseReqCfg.Parameters = append(baseReqCfg.Parameters, itemParam)
continue
}
@ -389,6 +375,7 @@ func (g *Generate) ParseReadConfigParam(requestCfg *define.UriBaseConfig, baseRe
Format: realInputTypeFormat,
Enum: ValidateRule.Enum(inputType.Field(i)),
XEnumDescription: ParseStructFieldTag.EnumDescription(inputType.Field(i)),
Example: ParseStructFieldTag.GetExampleValue(inputType.Field(i)),
},
})
continue
@ -434,6 +421,7 @@ func (g *Generate) ParseReadConfigParam(requestCfg *define.UriBaseConfig, baseRe
Format: realInputTypeFormat,
Enum: ValidateRule.Enum(inputType.Field(i)),
XEnumDescription: ParseStructFieldTag.EnumDescription(inputType.Field(i)),
Example: ParseStructFieldTag.GetExampleValue(inputType.Field(i)),
},
AllowEmptyValue: false,
Style: "",
@ -521,7 +509,6 @@ func (g *Generate) AddComponentsSchema(rootSchemaName string, pkgPath string, in
Items: propertyXOf,
}
}
return schemaName
}
// 结构体
@ -554,24 +541,13 @@ func (g *Generate) AddComponentsSchema(rootSchemaName string, pkgPath string, in
} else {
// 当做默认基础类型, 默认不会出现 *map *[]
convertBaseType, _ := g.realBaseType2SwaggerType(inputType.Field(i).Type.String())
maxVal := ValidateRule.Maximum(inputType.Field(i))
minVal := ValidateRule.Minimum(inputType.Field(i))
g.docData.Components.Schemas[schemaName].Properties[propertyName] = &define.Property{
Type: convertBaseType,
Format: inputType.Field(i).Type.String(),
Enum: ValidateRule.Enum(inputType.Field(i)),
XEnumDescription: ParseStructFieldTag.EnumDescription(inputType.Field(i)),
Default: ParseStructFieldTag.GetDefaultValue(inputType.Field(i)),
Description: ParseStructFieldTag.GetParamDesc(inputType.Field(i)),
}
if g.docData.Components.Schemas[schemaName].Properties[propertyName].Type == consts.SwaggerDataTypeString {
g.docData.Components.Schemas[schemaName].Properties[propertyName].MinLength = minVal
g.docData.Components.Schemas[schemaName].Properties[propertyName].MaxLength = maxVal
} else {
g.docData.Components.Schemas[schemaName].Properties[propertyName].Minimum = minVal
g.docData.Components.Schemas[schemaName].Properties[propertyName].Maximum = maxVal
}
}
// 设置参数各种属性
g.setStructFieldProperty(g.docData.Components.Schemas[schemaName], inputType.Field(i))
continue
}
if inputType.Field(i).Type.Kind() == reflect.Struct ||
@ -583,7 +559,6 @@ func (g *Generate) AddComponentsSchema(rootSchemaName string, pkgPath string, in
g.docData.Components.Schemas[schemaName].Properties[propertyName] = &define.Property{
Type: consts.SwaggerDataTypeObject,
Format: inputType.Field(i).Type.String(),
Description: ParseStructFieldTag.GetParamDesc(inputType.Field(i)),
Properties: map[string]*define.Property{},
}
} else if inputType.Field(i).Type.Kind() == reflect.Array ||
@ -602,7 +577,6 @@ func (g *Generate) AddComponentsSchema(rootSchemaName string, pkgPath string, in
g.docData.Components.Schemas[schemaName].Properties[propertyName] = &define.Property{
Type: consts.SwaggerDataTypeArray,
Format: inputType.Field(i).Type.String(),
Description: ParseStructFieldTag.GetParamDesc(inputType.Field(i)),
Items: propertyXOf,
}
} else {
@ -611,27 +585,17 @@ func (g *Generate) AddComponentsSchema(rootSchemaName string, pkgPath string, in
} else {
if inputType.Field(i).Type.Kind() == reflect.Interface {
g.docData.Components.Schemas[schemaName].Properties[propertyName] = g.anyTypeConfig(inputType.Field(i))
g.docData.Components.Schemas[schemaName].Properties[propertyName].Example = ParseStructFieldTag.GetExampleValue(inputType.Field(i))
} else {
convertBaseType, _ := g.realBaseType2SwaggerType(inputType.Field(i).Type.String())
maxVal := ValidateRule.Maximum(inputType.Field(i))
minVal := ValidateRule.Minimum(inputType.Field(i))
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 g.docData.Components.Schemas[schemaName].Properties[propertyName].Type == consts.SwaggerDataTypeString {
g.docData.Components.Schemas[schemaName].Properties[propertyName].MinLength = minVal
g.docData.Components.Schemas[schemaName].Properties[propertyName].MaxLength = maxVal
} else {
g.docData.Components.Schemas[schemaName].Properties[propertyName].Minimum = minVal
g.docData.Components.Schemas[schemaName].Properties[propertyName].Maximum = maxVal
}
}
}
// 设置参数各种属性
g.setStructFieldProperty(schemaName, inputType.Field(i))
g.setStructFieldProperty(g.docData.Components.Schemas[schemaName], inputType.Field(i))
}
return schemaName
}
@ -686,6 +650,7 @@ func (g *Generate) handleAnonymousField(schemaName string, field reflect.StructF
g.docData.Components.Schemas[schemaName].Properties[paramName] = &define.Property{
Type: baseConvertType,
Format: itemField.Type.String(),
Example: ParseStructFieldTag.GetExampleValue(itemField),
Enum: ValidateRule.Enum(itemField),
XEnumDescription: ParseStructFieldTag.EnumDescription(itemField),
Default: ParseStructFieldTag.GetDefaultValue(handleType.Field(i)),
@ -775,12 +740,34 @@ func (g *Generate) realBaseType2SwaggerType(realType string) (string, bool) {
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:13 2025/2/13
func (g *Generate) setStructFieldProperty(schemaName string, structField reflect.StructField) {
func (g *Generate) setStructFieldProperty(schema *define.Schema, structField reflect.StructField) {
paramName := ParseStructFieldTag.GetParamName(structField)
if ValidateRule.IsRequired(structField) {
g.docData.Components.Schemas[schemaName].Required = append(g.docData.Components.Schemas[schemaName].Required, paramName)
if paramName == "" || paramName == "-" {
return
}
isRequired := ValidateRule.IsRequired(structField)
enum := ValidateRule.Enum(structField)
xEnumDescription := ParseStructFieldTag.EnumDescription(structField)
example := ParseStructFieldTag.GetExampleValue(structField)
description := ParseStructFieldTag.GetParamDesc(structField)
maxVal := ValidateRule.Maximum(structField)
minVal := ValidateRule.Minimum(structField)
if nil != schema {
if isRequired {
schema.Required = append(schema.Required, paramName)
}
if schema.Properties[paramName].Type == consts.SwaggerDataTypeString {
schema.Properties[paramName].MinLength = minVal
schema.Properties[paramName].MaxLength = maxVal
} else {
schema.Properties[paramName].Minimum = minVal
schema.Properties[paramName].Maximum = maxVal
}
schema.Properties[paramName].Enum = enum
schema.Properties[paramName].XEnumDescription = xEnumDescription
schema.Properties[paramName].Example = example
schema.Properties[paramName].Description = description
}
g.docData.Components.Schemas[schemaName].Properties[ParseStructFieldTag.GetParamName(structField)].Enum = ValidateRule.Enum(structField)
}
// parseBaseUriConfig 通过Meta字段解析Uri基础配置信息

View File

@ -178,3 +178,19 @@ func (psf parseStructFieldTag) EnumDescription(structField reflect.StructField)
}
return res
}
// GetExampleValue 示例值
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 14:42 2025/2/20
func (psf parseStructFieldTag) GetExampleValue(structField reflect.StructField) string {
descTagList := []string{define.TagEg, define.TagExample}
for _, tag := range descTagList {
tagVal := structField.Tag.Get(tag)
if tagVal != "" {
return strings.ReplaceAll(tagVal, "###", "`")
}
}
return ""
}