diff --git a/protocol/goai/goai_requestbody.go b/protocol/goai/goai_requestbody.go index 7cc91ca86..1676623fc 100644 --- a/protocol/goai/goai_requestbody.go +++ b/protocol/goai/goai_requestbody.go @@ -47,18 +47,19 @@ func (oai *OpenApiV3) getRequestSchemaRef(in getRequestSchemaRefInput) (*SchemaR } var ( - dataFieldsPartsArray = gstr.Split(in.RequestDataField, ".") - bizRequestStructSchemaRef, bizRequestStructSchemaRefExist = oai.Components.Schemas[in.BusinessStructName] - schema, err = oai.structToSchema(in.RequestObject) + dataFieldsPartsArray = gstr.Split(in.RequestDataField, ".") + bizRequestStructSchemaRef = oai.Components.Schemas.Get(in.BusinessStructName) + schema, err = oai.structToSchema(in.RequestObject) ) if err != nil { return nil, err } - if in.RequestDataField == "" && bizRequestStructSchemaRefExist { + if in.RequestDataField == "" && bizRequestStructSchemaRef != nil { // Normal request. - for k, v := range bizRequestStructSchemaRef.Value.Properties { - schema.Properties[k] = v - } + bizRequestStructSchemaRef.Value.Properties.Iterator(func(key string, ref SchemaRef) bool { + schema.Properties.Set(key, ref) + return true + }) } else { // Common request. structFields, _ := gstructs.Fields(gstructs.FieldsInput{ @@ -76,7 +77,7 @@ func (oai *OpenApiV3) getRequestSchemaRef(in getRequestSchemaRefInput) (*SchemaR if err = oai.tagMapToSchema(structField.TagMap(), bizRequestStructSchemaRef.Value); err != nil { return nil, err } - schema.Properties[fieldName] = bizRequestStructSchemaRef + schema.Properties.Set(fieldName, *bizRequestStructSchemaRef) break } default: @@ -90,7 +91,7 @@ func (oai *OpenApiV3) getRequestSchemaRef(in getRequestSchemaRefInput) (*SchemaR if err != nil { return nil, err } - schema.Properties[fieldName] = *schemaRef + schema.Properties.Set(fieldName, *schemaRef) break } } diff --git a/protocol/goai/goai_response.go b/protocol/goai/goai_response.go index 8b47e51e1..059e4a443 100644 --- a/protocol/goai/goai_response.go +++ b/protocol/goai/goai_response.go @@ -51,18 +51,19 @@ func (oai *OpenApiV3) getResponseSchemaRef(in getResponseSchemaRefInput) (*Schem } var ( - dataFieldsPartsArray = gstr.Split(in.CommonResponseDataField, ".") - bizResponseStructSchemaRef, bizResponseStructSchemaRefExist = oai.Components.Schemas[in.BusinessStructName] - schema, err = oai.structToSchema(in.CommonResponseObject) + dataFieldsPartsArray = gstr.Split(in.CommonResponseDataField, ".") + bizResponseStructSchemaRef = oai.Components.Schemas.Get(in.BusinessStructName) + schema, err = oai.structToSchema(in.CommonResponseObject) ) if err != nil { return nil, err } - if in.CommonResponseDataField == "" && bizResponseStructSchemaRefExist { + if in.CommonResponseDataField == "" && bizResponseStructSchemaRef != nil { // Normal response. - for k, v := range bizResponseStructSchemaRef.Value.Properties { - schema.Properties[k] = v - } + bizResponseStructSchemaRef.Value.Properties.Iterator(func(key string, ref SchemaRef) bool { + schema.Properties.Set(key, ref) + return true + }) } else { // Common response. structFields, _ := gstructs.Fields(gstructs.FieldsInput{ @@ -80,7 +81,7 @@ func (oai *OpenApiV3) getResponseSchemaRef(in getResponseSchemaRefInput) (*Schem if err = oai.tagMapToSchema(structField.TagMap(), bizResponseStructSchemaRef.Value); err != nil { return nil, err } - schema.Properties[fieldName] = bizResponseStructSchemaRef + schema.Properties.Set(fieldName, *bizResponseStructSchemaRef) break } default: @@ -95,7 +96,7 @@ func (oai *OpenApiV3) getResponseSchemaRef(in getResponseSchemaRefInput) (*Schem if err != nil { return nil, err } - schema.Properties[fieldName] = *schemaRef + schema.Properties.Set(fieldName, *schemaRef) break } } diff --git a/protocol/goai/goai_shema.go b/protocol/goai/goai_shema.go index b1ebe2429..627c3e332 100644 --- a/protocol/goai/goai_shema.go +++ b/protocol/goai/goai_shema.go @@ -9,6 +9,7 @@ package goai import ( "reflect" + "github.com/gogf/gf/v2/container/gmap" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/internal/utils" "github.com/gogf/gf/v2/os/gstructs" @@ -18,8 +19,6 @@ import ( "github.com/gogf/gf/v2/util/gvalid" ) -type Schemas map[string]SchemaRef - // Schema is specified by OpenAPI/Swagger 3.0 standard. type Schema struct { OneOf SchemaRefs `json:"oneOf,omitempty" yaml:"oneOf,omitempty"` @@ -78,8 +77,8 @@ func (oai *OpenApiV3) addSchema(object ...interface{}) error { } func (oai *OpenApiV3) doAddSchemaSingle(object interface{}) error { - if oai.Components.Schemas == nil { - oai.Components.Schemas = map[string]SchemaRef{} + if oai.Components.Schemas.refs == nil { + oai.Components.Schemas.refs = gmap.NewListMap() } var ( @@ -88,21 +87,21 @@ func (oai *OpenApiV3) doAddSchemaSingle(object interface{}) error { ) // Already added. - if _, ok := oai.Components.Schemas[structTypeName]; ok { + if oai.Components.Schemas.Get(structTypeName) != nil { return nil } // Take the holder first. - oai.Components.Schemas[structTypeName] = SchemaRef{} + oai.Components.Schemas.Set(structTypeName, SchemaRef{}) schema, err := oai.structToSchema(object) if err != nil { return err } - oai.Components.Schemas[structTypeName] = SchemaRef{ + oai.Components.Schemas.Set(structTypeName, SchemaRef{ Ref: "", Value: schema, - } + }) return nil } @@ -111,7 +110,7 @@ func (oai *OpenApiV3) structToSchema(object interface{}) (*Schema, error) { var ( tagMap = gmeta.Data(object) schema = &Schema{ - Properties: map[string]SchemaRef{}, + Properties: createSchemas(), } ) if len(tagMap) > 0 { @@ -153,7 +152,7 @@ func (oai *OpenApiV3) structToSchema(object interface{}) (*Schema, error) { if err != nil { return nil, err } - schema.Properties[fieldName] = *schemaRef + schema.Properties.Set(fieldName, *schemaRef) } return schema, nil } diff --git a/protocol/goai/goai_shemaref.go b/protocol/goai/goai_shemaref.go index 1fd6a8bfa..ec6207c6e 100644 --- a/protocol/goai/goai_shemaref.go +++ b/protocol/goai/goai_shemaref.go @@ -70,7 +70,7 @@ func (oai *OpenApiV3) newSchemaRefWithGolangType(golangType reflect.Type, tagMap var ( structTypeName = oai.golangTypeToSchemaName(golangType) ) - if _, ok := oai.Components.Schemas[structTypeName]; !ok { + if oai.Components.Schemas.Get(structTypeName) == nil { if err := oai.addSchema(reflect.New(golangType).Interface()); err != nil { return nil, err } @@ -81,7 +81,7 @@ func (oai *OpenApiV3) newSchemaRefWithGolangType(golangType reflect.Type, tagMap default: // Normal struct object. var structTypeName = oai.golangTypeToSchemaName(golangType) - if _, ok := oai.Components.Schemas[structTypeName]; !ok { + if oai.Components.Schemas.Get(structTypeName) == nil { if err := oai.addSchema(reflect.New(golangType).Elem().Interface()); err != nil { return nil, err } diff --git a/protocol/goai/goai_shemas.go b/protocol/goai/goai_shemas.go new file mode 100644 index 000000000..c25b8ce00 --- /dev/null +++ b/protocol/goai/goai_shemas.go @@ -0,0 +1,64 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package goai + +import ( + "github.com/gogf/gf/v2/container/gmap" +) + +type Schemas struct { + refs *gmap.ListMap +} + +func createSchemas() Schemas { + return Schemas{ + refs: gmap.NewListMap(), + } +} + +func (s *Schemas) init() { + if s.refs == nil { + s.refs = gmap.NewListMap() + } +} + +func (s Schemas) Get(name string) *SchemaRef { + s.init() + value := s.refs.Get(name) + if value != nil { + ref := value.(SchemaRef) + return &ref + } + return nil +} + +func (s Schemas) Set(name string, ref SchemaRef) { + s.init() + s.refs.Set(name, ref) +} + +func (s Schemas) Map() map[string]SchemaRef { + s.init() + m := make(map[string]SchemaRef) + s.refs.Iterator(func(key, value interface{}) bool { + m[key.(string)] = value.(SchemaRef) + return true + }) + return m +} + +func (s Schemas) Iterator(f func(key string, ref SchemaRef) bool) { + s.init() + s.refs.Iterator(func(key, value interface{}) bool { + return f(key.(string), value.(SchemaRef)) + }) +} + +func (s Schemas) MarshalJSON() ([]byte, error) { + s.init() + return s.refs.MarshalJSON() +} diff --git a/protocol/goai/goai_z_unit_test.go b/protocol/goai/goai_z_unit_test.go index 3ae7645d9..7c734f74a 100644 --- a/protocol/goai/goai_z_unit_test.go +++ b/protocol/goai/goai_z_unit_test.go @@ -48,14 +48,14 @@ func Test_Basic(t *testing.T) { }) t.AssertNil(err) // Schema asserts. - t.Assert(len(oai.Components.Schemas), 2) - t.Assert(oai.Components.Schemas[`github.com.gogf.gf.v2.protocol.goai_test.CreateResourceReq`].Value.Type, goai.TypeObject) - t.Assert(len(oai.Components.Schemas[`github.com.gogf.gf.v2.protocol.goai_test.CreateResourceReq`].Value.Properties), 7) - t.Assert(oai.Components.Schemas[`github.com.gogf.gf.v2.protocol.goai_test.CreateResourceReq`].Value.Properties[`appId`].Value.Type, goai.TypeNumber) - t.Assert(oai.Components.Schemas[`github.com.gogf.gf.v2.protocol.goai_test.CreateResourceReq`].Value.Properties[`resourceId`].Value.Type, goai.TypeString) + t.Assert(len(oai.Components.Schemas.Map()), 2) + t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.protocol.goai_test.CreateResourceReq`).Value.Type, goai.TypeObject) + t.Assert(len(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.protocol.goai_test.CreateResourceReq`).Value.Properties.Map()), 7) + t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.protocol.goai_test.CreateResourceReq`).Value.Properties.Get(`appId`).Value.Type, goai.TypeNumber) + t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.protocol.goai_test.CreateResourceReq`).Value.Properties.Get(`resourceId`).Value.Type, goai.TypeString) - t.Assert(len(oai.Components.Schemas[`github.com.gogf.gf.v2.protocol.goai_test.SetSpecInfo`].Value.Properties), 3) - t.Assert(oai.Components.Schemas[`github.com.gogf.gf.v2.protocol.goai_test.SetSpecInfo`].Value.Properties[`Params`].Value.Type, goai.TypeArray) + t.Assert(len(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.protocol.goai_test.SetSpecInfo`).Value.Properties.Map()), 3) + t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.protocol.goai_test.SetSpecInfo`).Value.Properties.Get(`Params`).Value.Type, goai.TypeArray) }) } @@ -108,14 +108,14 @@ func TestOpenApiV3_Add(t *testing.T) { t.AssertNil(err) // fmt.Println(oai.String()) // Schema asserts. - t.Assert(len(oai.Components.Schemas), 3) - t.Assert(oai.Components.Schemas[`github.com.gogf.gf.v2.protocol.goai_test.CreateResourceReq`].Value.Type, goai.TypeObject) - t.Assert(len(oai.Components.Schemas[`github.com.gogf.gf.v2.protocol.goai_test.CreateResourceReq`].Value.Properties), 7) - t.Assert(oai.Components.Schemas[`github.com.gogf.gf.v2.protocol.goai_test.CreateResourceReq`].Value.Properties[`appId`].Value.Type, goai.TypeNumber) - t.Assert(oai.Components.Schemas[`github.com.gogf.gf.v2.protocol.goai_test.CreateResourceReq`].Value.Properties[`resourceId`].Value.Type, goai.TypeString) + t.Assert(len(oai.Components.Schemas.Map()), 3) + t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.protocol.goai_test.CreateResourceReq`).Value.Type, goai.TypeObject) + t.Assert(len(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.protocol.goai_test.CreateResourceReq`).Value.Properties.Map()), 7) + t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.protocol.goai_test.CreateResourceReq`).Value.Properties.Get(`appId`).Value.Type, goai.TypeNumber) + t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.protocol.goai_test.CreateResourceReq`).Value.Properties.Get(`resourceId`).Value.Type, goai.TypeString) - t.Assert(len(oai.Components.Schemas[`github.com.gogf.gf.v2.protocol.goai_test.SetSpecInfo`].Value.Properties), 3) - t.Assert(oai.Components.Schemas[`github.com.gogf.gf.v2.protocol.goai_test.SetSpecInfo`].Value.Properties[`Params`].Value.Type, goai.TypeArray) + t.Assert(len(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.protocol.goai_test.SetSpecInfo`).Value.Properties.Map()), 3) + t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.protocol.goai_test.SetSpecInfo`).Value.Properties.Get(`Params`).Value.Type, goai.TypeArray) // Paths. t.Assert(len(oai.Paths), 1) @@ -158,9 +158,9 @@ func TestOpenApiV3_Add_Recursive(t *testing.T) { }) t.AssertNil(err) // Schema asserts. - t.Assert(len(oai.Components.Schemas), 3) - t.Assert(oai.Components.Schemas[`github.com.gogf.gf.v2.protocol.goai_test.CategoryTreeItem`].Value.Type, goai.TypeObject) - t.Assert(len(oai.Components.Schemas[`github.com.gogf.gf.v2.protocol.goai_test.CategoryTreeItem`].Value.Properties), 3) + t.Assert(len(oai.Components.Schemas.Map()), 3) + t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.protocol.goai_test.CategoryTreeItem`).Value.Type, goai.TypeObject) + t.Assert(len(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.protocol.goai_test.CategoryTreeItem`).Value.Properties.Map()), 3) }) } @@ -222,7 +222,7 @@ func TestOpenApiV3_Add_AutoDetectIn(t *testing.T) { fmt.Println(oai.String()) - t.Assert(len(oai.Components.Schemas), 2) + t.Assert(len(oai.Components.Schemas.Map()), 2) t.Assert(len(oai.Paths), 1) t.AssertNE(oai.Paths[path].Get, nil) t.Assert(len(oai.Paths[path].Get.Parameters), 3) @@ -274,9 +274,9 @@ func TestOpenApiV3_CommonRequest(t *testing.T) { }) t.AssertNil(err) // Schema asserts. - t.Assert(len(oai.Components.Schemas), 3) + t.Assert(len(oai.Components.Schemas.Map()), 3) t.Assert(len(oai.Paths), 1) - t.Assert(len(oai.Paths["/index"].Put.RequestBody.Value.Content["application/json"].Schema.Value.Properties), 3) + t.Assert(len(oai.Paths["/index"].Put.RequestBody.Value.Content["application/json"].Schema.Value.Properties.Map()), 3) }) } @@ -319,9 +319,9 @@ func TestOpenApiV3_CommonRequest_WithoutDataField_Setting(t *testing.T) { t.AssertNil(err) // Schema asserts. // fmt.Println(oai.String()) - t.Assert(len(oai.Components.Schemas), 3) + t.Assert(len(oai.Components.Schemas.Map()), 3) t.Assert(len(oai.Paths), 1) - t.Assert(len(oai.Paths["/index"].Put.RequestBody.Value.Content["application/json"].Schema.Value.Properties), 5) + t.Assert(len(oai.Paths["/index"].Put.RequestBody.Value.Content["application/json"].Schema.Value.Properties.Map()), 5) }) } @@ -359,9 +359,9 @@ func TestOpenApiV3_CommonRequest_EmptyRequest(t *testing.T) { t.AssertNil(err) // Schema asserts. // fmt.Println(oai.String()) - t.Assert(len(oai.Components.Schemas), 3) + t.Assert(len(oai.Components.Schemas.Map()), 3) t.Assert(len(oai.Paths), 1) - t.Assert(len(oai.Paths["/index"].Put.RequestBody.Value.Content["application/json"].Schema.Value.Properties), 3) + t.Assert(len(oai.Paths["/index"].Put.RequestBody.Value.Content["application/json"].Schema.Value.Properties.Map()), 3) }) } @@ -414,10 +414,10 @@ func TestOpenApiV3_CommonRequest_SubDataField(t *testing.T) { t.AssertNil(err) // Schema asserts. // fmt.Println(oai.String()) - t.Assert(len(oai.Components.Schemas), 4) + t.Assert(len(oai.Components.Schemas.Map()), 4) t.Assert(len(oai.Paths), 1) - t.Assert(len(oai.Paths["/index"].Put.RequestBody.Value.Content["application/json"].Schema.Value.Properties), 1) - t.Assert(len(oai.Paths["/index"].Put.RequestBody.Value.Content["application/json"].Schema.Value.Properties[`Request`].Value.Properties), 4) + t.Assert(len(oai.Paths["/index"].Put.RequestBody.Value.Content["application/json"].Schema.Value.Properties.Map()), 1) + t.Assert(len(oai.Paths["/index"].Put.RequestBody.Value.Content["application/json"].Schema.Value.Properties.Get(`Request`).Value.Properties.Map()), 4) }) } @@ -460,13 +460,13 @@ func TestOpenApiV3_CommonResponse(t *testing.T) { }) t.AssertNil(err) - //g.Dump(oai.Paths["/index"].Get.Responses["200"].Value.Content["application/json"].Schema.Value.Properties) + //g.Dump(oai.Paths["/index"].Get.Responses["200"].Value.Content["application/json"].Schema.Value.Properties.Map()) // Schema asserts. - t.Assert(len(oai.Components.Schemas), 3) + t.Assert(len(oai.Components.Schemas.Map()), 3) t.Assert(len(oai.Paths), 1) - t.Assert(len(oai.Paths["/index"].Get.Responses["200"].Value.Content["application/json"].Schema.Value.Properties), 3) + t.Assert(len(oai.Paths["/index"].Get.Responses["200"].Value.Content["application/json"].Schema.Value.Properties.Map()), 3) t.Assert( - oai.Paths["/index"].Get.Responses["200"].Value.Content["application/json"].Schema.Value.Properties["data"].Value.Description, + oai.Paths["/index"].Get.Responses["200"].Value.Content["application/json"].Schema.Value.Properties.Get("data").Value.Description, `Result data for certain request according API definition`, ) }) @@ -511,9 +511,9 @@ func TestOpenApiV3_CommonResponse_WithoutDataField_Setting(t *testing.T) { t.AssertNil(err) // Schema asserts. fmt.Println(oai.String()) - t.Assert(len(oai.Components.Schemas), 3) + t.Assert(len(oai.Components.Schemas.Map()), 3) t.Assert(len(oai.Paths), 1) - t.Assert(len(oai.Paths["/index"].Get.Responses["200"].Value.Content["application/json"].Schema.Value.Properties), 8) + t.Assert(len(oai.Paths["/index"].Get.Responses["200"].Value.Content["application/json"].Schema.Value.Properties.Map()), 8) }) } @@ -551,10 +551,10 @@ func TestOpenApiV3_CommonResponse_EmptyResponse(t *testing.T) { t.AssertNil(err) // Schema asserts. // fmt.Println(oai.String()) - t.Assert(len(oai.Components.Schemas), 3) + t.Assert(len(oai.Components.Schemas.Map()), 3) t.Assert(len(oai.Paths), 1) t.Assert(oai.Paths["/index"].Put.RequestBody.Value.Content["application/json"].Schema.Ref, `github.com.gogf.gf.v2.protocol.goai_test.Req`) - t.Assert(len(oai.Paths["/index"].Put.Responses["200"].Value.Content["application/json"].Schema.Value.Properties), 3) + t.Assert(len(oai.Paths["/index"].Put.Responses["200"].Value.Content["application/json"].Schema.Value.Properties.Map()), 3) }) } @@ -607,10 +607,10 @@ func TestOpenApiV3_CommonResponse_SubDataField(t *testing.T) { t.AssertNil(err) // Schema asserts. // fmt.Println(oai.String()) - t.Assert(len(oai.Components.Schemas), 4) + t.Assert(len(oai.Components.Schemas.Map()), 4) t.Assert(len(oai.Paths), 1) - t.Assert(len(oai.Paths["/index"].Get.Responses["200"].Value.Content["application/json"].Schema.Value.Properties), 1) - t.Assert(len(oai.Paths["/index"].Get.Responses["200"].Value.Content["application/json"].Schema.Value.Properties[`Response`].Value.Properties), 7) + t.Assert(len(oai.Paths["/index"].Get.Responses["200"].Value.Content["application/json"].Schema.Value.Properties.Map()), 1) + t.Assert(len(oai.Paths["/index"].Get.Responses["200"].Value.Content["application/json"].Schema.Value.Properties.Get(`Response`).Value.Properties.Map()), 7) }) } @@ -663,12 +663,12 @@ func TestOpenApiV3_ShortTags(t *testing.T) { t.AssertNil(err) // fmt.Println(oai.String()) // Schema asserts. - t.Assert(len(oai.Components.Schemas), 3) + t.Assert(len(oai.Components.Schemas.Map()), 3) t.Assert(oai.Paths[`/test1/{appId}`].Summary, `CreateResourceReq sum`) t.Assert(oai. Components. - Schemas[`github.com.gogf.gf.v2.protocol.goai_test.CreateResourceReq`]. - Value.Properties[`resourceId`].Value.Description, `资源Id`) + Schemas.Get(`github.com.gogf.gf.v2.protocol.goai_test.CreateResourceReq`). + Value.Properties.Get(`resourceId`).Value.Description, `资源Id`) }) } @@ -698,7 +698,7 @@ func TestOpenApiV3_HtmlResponse(t *testing.T) { t.AssertNil(err) // fmt.Println(oai.String()) - t.Assert(oai.Components.Schemas[`github.com.gogf.gf.v2.protocol.goai_test.Res`].Value.Type, goai.TypeString) + t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.protocol.goai_test.Res`).Value.Type, goai.TypeString) }) } @@ -745,6 +745,6 @@ func TestOpenApiV3_HtmlResponseWithCommonResponse(t *testing.T) { t.AssertNil(err) // fmt.Println(oai.String()) - t.Assert(oai.Components.Schemas[`github.com.gogf.gf.v2.protocol.goai_test.Res`].Value.Type, goai.TypeString) + t.Assert(oai.Components.Schemas.Get(`github.com.gogf.gf.v2.protocol.goai_test.Res`).Value.Type, goai.TypeString) }) }