diff --git a/cmd/gf/internal/cmd/cmd_gen_service.go b/cmd/gf/internal/cmd/cmd_gen_service.go index f1a61562c..8c6415d89 100644 --- a/cmd/gf/internal/cmd/cmd_gen_service.go +++ b/cmd/gf/internal/cmd/cmd_gen_service.go @@ -331,6 +331,10 @@ func (c cGenService) generateServiceFiles( mlog.Printf(`not overwrite, ignore generating service go file: %s`, filePath) continue } + if !utils.IsFileDoNotEdit(filePath) { + mlog.Printf(`ignore file as it is manually maintained: %s`, filePath) + continue + } if !c.isToGenerateServiceGoFile(filePath, funcArray) { mlog.Printf(`not dirty, ignore generating service go file: %s`, filePath) continue @@ -347,10 +351,6 @@ func (c cGenService) generateServiceFiles( // isToGenerateServiceGoFile checks and returns whether the service content dirty. func (c cGenService) isToGenerateServiceGoFile(filePath string, funcArray *garray.StrArray) bool { - if !utils.IsFileDoNotEdit(filePath) { - mlog.Debugf(`ignore file as it is manually maintained: %s`, filePath) - return false - } var ( fileContent = gfile.GetContents(filePath) generatedFuncArray = garray.NewSortedStrArrayFrom(funcArray.Slice()) diff --git a/cmd/gf/internal/consts/consts_gen_service_template.go b/cmd/gf/internal/consts/consts_gen_service_template.go index 6cc9a286c..19bfe2a56 100644 --- a/cmd/gf/internal/consts/consts_gen_service_template.go +++ b/cmd/gf/internal/consts/consts_gen_service_template.go @@ -1,9 +1,10 @@ package consts const TemplateGenServiceContent = ` -// ========================================================================== +// ================================================================================ // Code generated by GoFrame CLI tool. DO NOT EDIT. -// ========================================================================== +// You can delete these comments if you wish manually maintain this interface file. +// ================================================================================ package {PackageName} diff --git a/net/goai/goai.go b/net/goai/goai.go index e25d6e296..119c29b2f 100644 --- a/net/goai/goai.go +++ b/net/goai/goai.go @@ -202,6 +202,9 @@ func (oai *OpenApiV3) golangTypeToOAIFormat(t reflect.Type) string { return FormatBinary default: + if oai.isEmbeddedStructDefinition(t) { + return `EmbeddedStructDefinition` + } return format } } diff --git a/net/goai/goai_shema_ref.go b/net/goai/goai_shema_ref.go index 0d8327f87..54103c425 100644 --- a/net/goai/goai_shema_ref.go +++ b/net/goai/goai_shema_ref.go @@ -10,6 +10,7 @@ import ( "reflect" "github.com/gogf/gf/v2/internal/json" + "github.com/gogf/gf/v2/text/gstr" ) type SchemaRefs []SchemaRef @@ -19,8 +20,25 @@ type SchemaRef struct { Value *Schema } +// isEmbeddedStructDefine checks and returns whether given golang type is embedded struct definition, like: +// struct A struct{ +// B struct{ +// // ... +// } +// } +// The `B` in `A` is called `embedded struct definition`. +func (oai *OpenApiV3) isEmbeddedStructDefinition(golangType reflect.Type) bool { + s := golangType.String() + if gstr.Contains(s, `struct {`) { + return true + } + return false +} + +// newSchemaRefWithGolangType creates a new Schema and returns its SchemaRef. func (oai *OpenApiV3) newSchemaRefWithGolangType(golangType reflect.Type, tagMap map[string]string) (*SchemaRef, error) { var ( + err error oaiType = oai.golangTypeToOAIType(golangType) oaiFormat = oai.golangTypeToOAIFormat(golangType) schemaRef = &SchemaRef{} @@ -85,15 +103,24 @@ func (oai *OpenApiV3) newSchemaRefWithGolangType(golangType reflect.Type, tagMap schemaRef.Value = nil default: - // Normal struct object. - var structTypeName = oai.golangTypeToSchemaName(golangType) - if oai.Components.Schemas.Get(structTypeName) == nil { - if err := oai.addSchema(reflect.New(golangType).Elem().Interface()); err != nil { + golangTypeInstance := reflect.New(golangType).Elem().Interface() + if oai.isEmbeddedStructDefinition(golangType) { + schema, err = oai.structToSchema(golangTypeInstance) + if err != nil { return nil, err } + schemaRef.Ref = "" + schemaRef.Value = schema + } else { + var structTypeName = oai.golangTypeToSchemaName(golangType) + if oai.Components.Schemas.Get(structTypeName) == nil { + if err := oai.addSchema(golangTypeInstance); err != nil { + return nil, err + } + } + schemaRef.Ref = structTypeName + schemaRef.Value = nil } - schemaRef.Ref = structTypeName - schemaRef.Value = nil } } return schemaRef, nil diff --git a/net/goai/goai_z_unit_test.go b/net/goai/goai_z_unit_test.go index 90589215d..d6af7e983 100644 --- a/net/goai/goai_z_unit_test.go +++ b/net/goai/goai_z_unit_test.go @@ -12,6 +12,7 @@ import ( "testing" "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/internal/json" "github.com/gogf/gf/v2/net/goai" "github.com/gogf/gf/v2/test/gtest" "github.com/gogf/gf/v2/util/gmeta" @@ -937,7 +938,7 @@ func Test_EnumOfSchemaItems(t *testing.T) { }) } -func Test_AliasNameOfAtrribute(t *testing.T) { +func Test_AliasNameOfAttribute(t *testing.T) { type CreateResourceReq struct { gmeta.Meta `path:"/CreateResourceReq" method:"POST"` Name string `p:"n"` @@ -973,3 +974,29 @@ func Test_AliasNameOfAtrribute(t *testing.T) { ) }) } + +func Test_EmbeddedStructAttribute(t *testing.T) { + type CreateResourceReq struct { + gmeta.Meta `path:"/CreateResourceReq" method:"POST"` + Name string `dc:"This is name."` + Embedded struct { + Age uint `dc:"This is embedded age."` + } + } + + gtest.C(t, func(t *gtest.T) { + var ( + err error + oai = goai.New() + req = new(CreateResourceReq) + ) + err = oai.Add(goai.AddInput{ + Object: req, + }) + t.AssertNil(err) + + b, err := json.Marshal(oai) + t.AssertNil(err) + t.Assert(b, `{"openapi":"3.0.0","components":{"schemas":{"github.com.gogf.gf.v2.net.goai_test.CreateResourceReq":{"properties":{"Name":{"description":"This is name.","format":"string","properties":{},"type":"string"},"Embedded":{"properties":{"Age":{"description":"This is embedded age.","format":"uint","properties":{},"type":"integer"}},"type":"object"}},"type":"object"}}},"info":{"title":"","version":""},"paths":null}`) + }) +}