package swagger import ( "net/http" "strings" "github.com/go-openapi/spec" apiSpec "github.com/zeromicro/go-zero/tools/goctl/api/spec" ) func isPostJson(ctx Context, method string, tp apiSpec.Type) (string, bool) { // Check if this is a method that supports request body (POST, PUT, PATCH) if !strings.EqualFold(method, http.MethodPost) && !strings.EqualFold(method, http.MethodPut) && !strings.EqualFold(method, http.MethodPatch) { return "", false } structType, ok := tp.(apiSpec.DefineStruct) if !ok { return "", false } var hasJsonField bool rangeMemberAndDo(ctx, structType, func(tag *apiSpec.Tags, required bool, member apiSpec.Member) { jsonTag, _ := tag.Get(tagJson) if !hasJsonField { hasJsonField = jsonTag != nil } }) return structType.RawName, hasJsonField } func parametersFromType(ctx Context, method string, tp apiSpec.Type) []spec.Parameter { if tp == nil { return []spec.Parameter{} } structType, ok := tp.(apiSpec.DefineStruct) if !ok { return []spec.Parameter{} } var ( resp []spec.Parameter properties = map[string]spec.Schema{} requiredFields []string ) rangeMemberAndDo(ctx, structType, func(tag *apiSpec.Tags, required bool, member apiSpec.Member) { headerTag, _ := tag.Get(tagHeader) hasHeader := headerTag != nil pathParameterTag, _ := tag.Get(tagPath) hasPathParameter := pathParameterTag != nil formTag, _ := tag.Get(tagForm) hasForm := formTag != nil jsonTag, _ := tag.Get(tagJson) hasJson := jsonTag != nil if hasHeader { minimum, maximum, exclusiveMinimum, exclusiveMaximum := rangeValueFromOptions(headerTag.Options) resp = append(resp, spec.Parameter{ CommonValidations: spec.CommonValidations{ Maximum: maximum, ExclusiveMaximum: exclusiveMaximum, Minimum: minimum, ExclusiveMinimum: exclusiveMinimum, Enum: enumsValueFromOptions(headerTag.Options), }, SimpleSchema: spec.SimpleSchema{ Type: sampleTypeFromGoType(ctx, member.Type), Default: defValueFromOptions(ctx, headerTag.Options, member.Type), Items: sampleItemsFromGoType(ctx, member.Type), }, ParamProps: spec.ParamProps{ In: paramsInHeader, Name: headerTag.Name, Description: formatComment(member.Comment), Required: required, }, }) } if hasPathParameter { minimum, maximum, exclusiveMinimum, exclusiveMaximum := rangeValueFromOptions(pathParameterTag.Options) resp = append(resp, spec.Parameter{ CommonValidations: spec.CommonValidations{ Maximum: maximum, ExclusiveMaximum: exclusiveMaximum, Minimum: minimum, ExclusiveMinimum: exclusiveMinimum, Enum: enumsValueFromOptions(pathParameterTag.Options), }, SimpleSchema: spec.SimpleSchema{ Type: sampleTypeFromGoType(ctx, member.Type), Default: defValueFromOptions(ctx, pathParameterTag.Options, member.Type), Items: sampleItemsFromGoType(ctx, member.Type), }, ParamProps: spec.ParamProps{ In: paramsInPath, Name: pathParameterTag.Name, Description: formatComment(member.Comment), Required: required, }, }) } if hasForm { minimum, maximum, exclusiveMinimum, exclusiveMaximum := rangeValueFromOptions(formTag.Options) if strings.EqualFold(method, http.MethodGet) { resp = append(resp, spec.Parameter{ CommonValidations: spec.CommonValidations{ Maximum: maximum, ExclusiveMaximum: exclusiveMaximum, Minimum: minimum, ExclusiveMinimum: exclusiveMinimum, Enum: enumsValueFromOptions(formTag.Options), }, SimpleSchema: spec.SimpleSchema{ Type: sampleTypeFromGoType(ctx, member.Type), Default: defValueFromOptions(ctx, formTag.Options, member.Type), Items: sampleItemsFromGoType(ctx, member.Type), }, ParamProps: spec.ParamProps{ In: paramsInQuery, Name: formTag.Name, Description: formatComment(member.Comment), Required: required, AllowEmptyValue: !required, }, }) } else { resp = append(resp, spec.Parameter{ CommonValidations: spec.CommonValidations{ Maximum: maximum, ExclusiveMaximum: exclusiveMaximum, Minimum: minimum, ExclusiveMinimum: exclusiveMinimum, Enum: enumsValueFromOptions(formTag.Options), }, SimpleSchema: spec.SimpleSchema{ Type: sampleTypeFromGoType(ctx, member.Type), Default: defValueFromOptions(ctx, formTag.Options, member.Type), Items: sampleItemsFromGoType(ctx, member.Type), }, ParamProps: spec.ParamProps{ In: paramsInForm, Name: formTag.Name, Description: formatComment(member.Comment), Required: required, AllowEmptyValue: !required, }, }) } } if hasJson { minimum, maximum, exclusiveMinimum, exclusiveMaximum := rangeValueFromOptions(jsonTag.Options) if required { requiredFields = append(requiredFields, jsonTag.Name) } var schema = spec.Schema{ SwaggerSchemaProps: spec.SwaggerSchemaProps{ Example: exampleValueFromOptions(ctx, jsonTag.Options, member.Type), }, SchemaProps: spec.SchemaProps{ Description: formatComment(member.Comment), Type: typeFromGoType(ctx, member.Type), Default: defValueFromOptions(ctx, jsonTag.Options, member.Type), Maximum: maximum, ExclusiveMaximum: exclusiveMaximum, Minimum: minimum, ExclusiveMinimum: exclusiveMinimum, Enum: enumsValueFromOptions(jsonTag.Options), AdditionalProperties: mapFromGoType(ctx, member.Type), }, } switch sampleTypeFromGoType(ctx, member.Type) { case swaggerTypeArray: schema.Items = itemsFromGoType(ctx, member.Type) case swaggerTypeObject: p, r := propertiesFromType(ctx, member.Type) schema.Properties = p schema.Required = r } properties[jsonTag.Name] = schema } }) if len(properties) > 0 { if ctx.UseDefinitions { structName, ok := isPostJson(ctx, method, tp) if ok { resp = append(resp, spec.Parameter{ ParamProps: spec.ParamProps{ In: paramsInBody, Name: paramsInBody, Required: true, Schema: &spec.Schema{ SchemaProps: spec.SchemaProps{ Ref: spec.MustCreateRef(getRefName(structName)), }, }, }, }) } } else { resp = append(resp, spec.Parameter{ ParamProps: spec.ParamProps{ In: paramsInBody, Name: paramsInBody, Required: true, Schema: &spec.Schema{ SchemaProps: spec.SchemaProps{ Type: typeFromGoType(ctx, structType), Properties: properties, Required: requiredFields, }, }, }, }) } } return resp }