From 36159b88d98656aabadec99b5c6ff54f250f1b36 Mon Sep 17 00:00:00 2001 From: Peter Broadhurst Date: Tue, 23 Nov 2021 14:04:41 -0500 Subject: [PATCH 01/13] Do not clear refs on recursive type references --- openapi3gen/openapi3gen.go | 4 +++- openapi3gen/openapi3gen_test.go | 38 +++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/openapi3gen/openapi3gen.go b/openapi3gen/openapi3gen.go index b4ae7b04c..b21a4e862 100644 --- a/openapi3gen/openapi3gen.go +++ b/openapi3gen/openapi3gen.go @@ -57,7 +57,9 @@ func NewSchemaRefForValue(value interface{}, opts ...Option) (*openapi3.SchemaRe g := NewGenerator(opts...) ref, err := g.GenerateSchemaRef(reflect.TypeOf(value)) for ref := range g.SchemaRefs { - ref.Ref = "" + if !strings.HasPrefix(ref.Ref, "#/") { + ref.Ref = "" + } } return ref, g.SchemaRefs, err } diff --git a/openapi3gen/openapi3gen_test.go b/openapi3gen/openapi3gen_test.go index 6d96db98e..79f74bf46 100644 --- a/openapi3gen/openapi3gen_test.go +++ b/openapi3gen/openapi3gen_test.go @@ -246,3 +246,41 @@ func TestSchemaCustomizerError(t *testing.T) { })) require.EqualError(t, err, "test error") } + +func TestRecursiveSchema(t *testing.T) { + + type RecursiveType struct { + Field1 string `json:"field1"` + Field2 string `json:"field2"` + Field3 string `json:"field3"` + Components []*RecursiveType `json:"children,omitempty"` + } + + schemaRef, _, err := NewSchemaRefForValue(&RecursiveType{}) + require.NoError(t, err) + + jsonSchema, err := schemaRef.MarshalJSON() + require.NoError(t, err) + + require.JSONEq(t, `{ + "properties": { + "children": { + "items": { + "$ref": "#/components/schemas/RecursiveType" + }, + "type": "array" + }, + "field1": { + "type": "string" + }, + "field2": { + "type": "string" + }, + "field3": { + "type": "string" + } + }, + "type": "object" + }`, string(jsonSchema)) + +} From 2f25aeab5455a530d70dc514da430abd956f2760 Mon Sep 17 00:00:00 2001 From: Peter Broadhurst Date: Tue, 23 Nov 2021 23:41:22 -0500 Subject: [PATCH 02/13] Provide a new function to return dependent schemas --- openapi3gen/openapi3gen.go | 32 +++++++++++++++++++++++++++----- openapi3gen/openapi3gen_test.go | 33 ++++++++++++++++++++++++++++++--- 2 files changed, 57 insertions(+), 8 deletions(-) diff --git a/openapi3gen/openapi3gen.go b/openapi3gen/openapi3gen.go index b21a4e862..8ed8f1881 100644 --- a/openapi3gen/openapi3gen.go +++ b/openapi3gen/openapi3gen.go @@ -57,11 +57,28 @@ func NewSchemaRefForValue(value interface{}, opts ...Option) (*openapi3.SchemaRe g := NewGenerator(opts...) ref, err := g.GenerateSchemaRef(reflect.TypeOf(value)) for ref := range g.SchemaRefs { - if !strings.HasPrefix(ref.Ref, "#/") { + ref.Ref = "" + } + return ref, g.SchemaRefs, err +} + +// NewSchemaRefAndComponentsForValue returns the ref for this schema, and an array of dependent component schemas +func NewSchemaRefAndComponentsForValue(value interface{}, schemas openapi3.Schemas, opts ...Option) (*openapi3.SchemaRef, error) { + g := NewGenerator(opts...) + ref, err := g.GenerateSchemaRef(reflect.TypeOf(value)) + for ref := range g.SchemaRefs { + if g.ComponentSchemas[ref.Ref] { + schemas[ref.Ref] = &openapi3.SchemaRef{ + Value: ref.Value, + } + } + if strings.HasPrefix(ref.Ref, "#/components/schemas/") { + ref.Value = nil + } else { ref.Ref = "" } } - return ref, g.SchemaRefs, err + return ref, err } type Generator struct { @@ -73,6 +90,9 @@ type Generator struct { // If count is 1, it's not ne // An OpenAPI identifier has been assigned to each. SchemaRefs map[*openapi3.SchemaRef]int + + // ComponentSchemas contains a map of schemas that must be defined in the components, due to cycles + ComponentSchemas map[string]bool } func NewGenerator(opts ...Option) *Generator { @@ -81,9 +101,10 @@ func NewGenerator(opts ...Option) *Generator { f(gOpt) } return &Generator{ - Types: make(map[reflect.Type]*openapi3.SchemaRef), - SchemaRefs: make(map[*openapi3.SchemaRef]int), - opts: *gOpt, + Types: make(map[reflect.Type]*openapi3.SchemaRef), + SchemaRefs: make(map[*openapi3.SchemaRef]int), + ComponentSchemas: make(map[string]bool), + opts: *gOpt, } } @@ -343,6 +364,7 @@ func (g *Generator) generateCycleSchemaRef(t reflect.Type, schema *openapi3.Sche typeName = t.Name() } + g.ComponentSchemas[typeName] = true return openapi3.NewSchemaRef(fmt.Sprintf("#/components/schemas/%s", typeName), schema) } diff --git a/openapi3gen/openapi3gen_test.go b/openapi3gen/openapi3gen_test.go index 79f74bf46..64be849e8 100644 --- a/openapi3gen/openapi3gen_test.go +++ b/openapi3gen/openapi3gen_test.go @@ -256,12 +256,39 @@ func TestRecursiveSchema(t *testing.T) { Components []*RecursiveType `json:"children,omitempty"` } - schemaRef, _, err := NewSchemaRefForValue(&RecursiveType{}) + schemas := make(openapi3.Schemas) + schemaRef, err := NewSchemaRefAndComponentsForValue(&RecursiveType{}, schemas) require.NoError(t, err) - jsonSchema, err := schemaRef.MarshalJSON() + jsonSchemas, err := json.MarshalIndent(&schemas, "", " ") require.NoError(t, err) + jsonSchemaRef, err := json.MarshalIndent(&schemaRef, "", " ") + require.NoError(t, err) + + require.JSONEq(t, `{ + "RecursiveType": { + "properties": { + "children": { + "items": { + "$ref": "#/components/schemas/RecursiveType" + }, + "type": "array" + }, + "field1": { + "type": "string" + }, + "field2": { + "type": "string" + }, + "field3": { + "type": "string" + } + }, + "type": "object" + } + }`, string(jsonSchemas)) + require.JSONEq(t, `{ "properties": { "children": { @@ -281,6 +308,6 @@ func TestRecursiveSchema(t *testing.T) { } }, "type": "object" - }`, string(jsonSchema)) + }`, string(jsonSchemaRef)) } From d0b8b6307f84a57fde3c0f6df84f628f4f547e25 Mon Sep 17 00:00:00 2001 From: Peter Broadhurst Date: Wed, 24 Nov 2021 14:47:40 -0500 Subject: [PATCH 03/13] Update syntax of NewSchemaRefForValue, rather than new method --- openapi3gen/openapi3gen.go | 46 ++++++------- openapi3gen/openapi3gen_test.go | 110 ++++++++++++++++++++++++++++++-- openapi3gen/simple_test.go | 6 +- 3 files changed, 124 insertions(+), 38 deletions(-) diff --git a/openapi3gen/openapi3gen.go b/openapi3gen/openapi3gen.go index 8ed8f1881..7b874be5d 100644 --- a/openapi3gen/openapi3gen.go +++ b/openapi3gen/openapi3gen.go @@ -52,33 +52,10 @@ func SchemaCustomizer(sc SchemaCustomizerFn) Option { return func(x *generatorOpt) { x.schemaCustomizer = sc } } -// NewSchemaRefForValue uses reflection on the given value to produce a SchemaRef. -func NewSchemaRefForValue(value interface{}, opts ...Option) (*openapi3.SchemaRef, map[*openapi3.SchemaRef]int, error) { +// NewSchemaRefForValue returns the ref for this schema, and an array of dependent component schemas +func NewSchemaRefForValue(value interface{}, schemas openapi3.Schemas, opts ...Option) (*openapi3.SchemaRef, error) { g := NewGenerator(opts...) - ref, err := g.GenerateSchemaRef(reflect.TypeOf(value)) - for ref := range g.SchemaRefs { - ref.Ref = "" - } - return ref, g.SchemaRefs, err -} - -// NewSchemaRefAndComponentsForValue returns the ref for this schema, and an array of dependent component schemas -func NewSchemaRefAndComponentsForValue(value interface{}, schemas openapi3.Schemas, opts ...Option) (*openapi3.SchemaRef, error) { - g := NewGenerator(opts...) - ref, err := g.GenerateSchemaRef(reflect.TypeOf(value)) - for ref := range g.SchemaRefs { - if g.ComponentSchemas[ref.Ref] { - schemas[ref.Ref] = &openapi3.SchemaRef{ - Value: ref.Value, - } - } - if strings.HasPrefix(ref.Ref, "#/components/schemas/") { - ref.Value = nil - } else { - ref.Ref = "" - } - } - return ref, err + return g.newSchemaRefForValue(value, schemas) } type Generator struct { @@ -113,6 +90,23 @@ func (g *Generator) GenerateSchemaRef(t reflect.Type) (*openapi3.SchemaRef, erro return g.generateSchemaRefFor(nil, t, "_root", "") } +func (g *Generator) newSchemaRefForValue(value interface{}, schemas openapi3.Schemas) (*openapi3.SchemaRef, error) { + ref, err := g.GenerateSchemaRef(reflect.TypeOf(value)) + for ref := range g.SchemaRefs { + if g.ComponentSchemas[ref.Ref] && schemas != nil { + schemas[ref.Ref] = &openapi3.SchemaRef{ + Value: ref.Value, + } + } + if strings.HasPrefix(ref.Ref, "#/components/schemas/") { + ref.Value = nil + } else { + ref.Ref = "" + } + } + return ref, err +} + func (g *Generator) generateSchemaRefFor(parents []*jsoninfo.TypeInfo, t reflect.Type, name string, tag reflect.StructTag) (*openapi3.SchemaRef, error) { if ref := g.Types[t]; ref != nil && g.opts.schemaCustomizer == nil { g.SchemaRefs[ref]++ diff --git a/openapi3gen/openapi3gen_test.go b/openapi3gen/openapi3gen_test.go index 64be849e8..ee8530c8f 100644 --- a/openapi3gen/openapi3gen_test.go +++ b/openapi3gen/openapi3gen_test.go @@ -7,6 +7,7 @@ import ( "strconv" "strings" "testing" + "time" "github.com/getkin/kin-openapi/openapi3" "github.com/stretchr/testify/require" @@ -19,11 +20,106 @@ type CyclicType1 struct { CyclicField *CyclicType0 `json:"b"` } +func TestSimpleStruct(t *testing.T) { + type SomeOtherType string + + type SomeStruct struct { + Bool bool `json:"bool"` + Int int `json:"int"` + Int64 int64 `json:"int64"` + Float64 float64 `json:"float64"` + String string `json:"string"` + Bytes []byte `json:"bytes"` + JSON json.RawMessage `json:"json"` + Time time.Time `json:"time"` + Slice []SomeOtherType `json:"slice"` + Map map[string]*SomeOtherType `json:"map"` + + Struct struct { + X string `json:"x"` + } `json:"struct"` + + EmptyStruct struct { + Y string + } `json:"structWithoutFields"` + + Ptr *SomeOtherType `json:"ptr"` + } + + g := NewGenerator() + schemaRef, err := g.newSchemaRefForValue(&SomeStruct{}, nil) + require.NoError(t, err) + require.Len(t, g.SchemaRefs, 15) + + schemaJSON, err := json.Marshal(schemaRef) + require.NoError(t, err) + + require.JSONEq(t, ` + { + "properties": { + "bool": { + "type": "boolean" + }, + "bytes": { + "format": "byte", + "type": "string" + }, + "float64": { + "format": "double", + "type": "number" + }, + "int": { + "type": "integer" + }, + "int64": { + "format": "int64", + "type": "integer" + }, + "json": {}, + "map": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "ptr": { + "type": "string" + }, + "slice": { + "items": { + "type": "string" + }, + "type": "array" + }, + "string": { + "type": "string" + }, + "struct": { + "properties": { + "x": { + "type": "string" + } + }, + "type": "object" + }, + "structWithoutFields": {}, + "time": { + "format": "date-time", + "type": "string" + } + }, + "type": "object" + } + `, string(schemaJSON)) + +} + func TestCyclic(t *testing.T) { - schemaRef, refsMap, err := NewSchemaRefForValue(&CyclicType0{}, ThrowErrorOnCycle()) + g := NewGenerator(ThrowErrorOnCycle()) + schemaRef, err := g.newSchemaRefForValue(&CyclicType0{}, nil) require.IsType(t, &CycleError{}, err) require.Nil(t, schemaRef) - require.Empty(t, refsMap) + require.Empty(t, g.SchemaRefs) } func TestExportedNonTagged(t *testing.T) { @@ -34,7 +130,7 @@ func TestExportedNonTagged(t *testing.T) { EvenAYaml string `yaml:"even_a_yaml"` } - schemaRef, _, err := NewSchemaRefForValue(&Bla{}, UseAllExportedFields()) + schemaRef, err := NewSchemaRefForValue(&Bla{}, nil, UseAllExportedFields()) require.NoError(t, err) require.Equal(t, &openapi3.SchemaRef{Value: &openapi3.Schema{ Type: "object", @@ -50,7 +146,7 @@ func TestExportUint(t *testing.T) { UnsignedInt uint `json:"uint"` } - schemaRef, _, err := NewSchemaRefForValue(&UnsignedIntStruct{}, UseAllExportedFields()) + schemaRef, err := NewSchemaRefForValue(&UnsignedIntStruct{}, nil, UseAllExportedFields()) require.NoError(t, err) require.Equal(t, &openapi3.SchemaRef{Value: &openapi3.Schema{ Type: "object", @@ -169,7 +265,7 @@ func TestSchemaCustomizer(t *testing.T) { EnumField3 string `json:"enum3" myenumtag:"e,f"` } - schemaRef, _, err := NewSchemaRefForValue(&Bla{}, UseAllExportedFields(), SchemaCustomizer(func(name string, ft reflect.Type, tag reflect.StructTag, schema *openapi3.Schema) error { + schemaRef, err := NewSchemaRefForValue(&Bla{}, nil, UseAllExportedFields(), SchemaCustomizer(func(name string, ft reflect.Type, tag reflect.StructTag, schema *openapi3.Schema) error { t.Logf("Field=%s,Tag=%s", name, tag) if tag.Get("mymintag") != "" { minVal, err := strconv.ParseFloat(tag.Get("mymintag"), 64) @@ -241,7 +337,7 @@ func TestSchemaCustomizer(t *testing.T) { func TestSchemaCustomizerError(t *testing.T) { type Bla struct{} - _, _, err := NewSchemaRefForValue(&Bla{}, UseAllExportedFields(), SchemaCustomizer(func(name string, ft reflect.Type, tag reflect.StructTag, schema *openapi3.Schema) error { + _, err := NewSchemaRefForValue(&Bla{}, nil, UseAllExportedFields(), SchemaCustomizer(func(name string, ft reflect.Type, tag reflect.StructTag, schema *openapi3.Schema) error { return errors.New("test error") })) require.EqualError(t, err, "test error") @@ -257,7 +353,7 @@ func TestRecursiveSchema(t *testing.T) { } schemas := make(openapi3.Schemas) - schemaRef, err := NewSchemaRefAndComponentsForValue(&RecursiveType{}, schemas) + schemaRef, err := NewSchemaRefForValue(&RecursiveType{}, schemas) require.NoError(t, err) jsonSchemas, err := json.MarshalIndent(&schemas, "", " ") diff --git a/openapi3gen/simple_test.go b/openapi3gen/simple_test.go index d997e23b2..99e94ae12 100644 --- a/openapi3gen/simple_test.go +++ b/openapi3gen/simple_test.go @@ -36,15 +36,11 @@ type ( ) func Example() { - schemaRef, refsMap, err := openapi3gen.NewSchemaRefForValue(&SomeStruct{}) + schemaRef, err := openapi3gen.NewSchemaRefForValue(&SomeStruct{}, nil) if err != nil { panic(err) } - if len(refsMap) != 15 { - panic(fmt.Sprintf("unintended len(refsMap) = %d", len(refsMap))) - } - data, err := json.MarshalIndent(schemaRef, "", " ") if err != nil { panic(err) From f24e6dc2ad4529f7d73ba74bff12662c69ee23c5 Mon Sep 17 00:00:00 2001 From: Peter Broadhurst Date: Wed, 24 Nov 2021 14:51:55 -0500 Subject: [PATCH 04/13] Re-instate original comment --- openapi3gen/openapi3gen.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openapi3gen/openapi3gen.go b/openapi3gen/openapi3gen.go index 7b874be5d..1c233be12 100644 --- a/openapi3gen/openapi3gen.go +++ b/openapi3gen/openapi3gen.go @@ -52,7 +52,7 @@ func SchemaCustomizer(sc SchemaCustomizerFn) Option { return func(x *generatorOpt) { x.schemaCustomizer = sc } } -// NewSchemaRefForValue returns the ref for this schema, and an array of dependent component schemas +// NewSchemaRefForValue uses reflection on the given value to produce a SchemaRef, and updates a supplied map with any dependent component schemas (for cycles) func NewSchemaRefForValue(value interface{}, schemas openapi3.Schemas, opts ...Option) (*openapi3.SchemaRef, error) { g := NewGenerator(opts...) return g.newSchemaRefForValue(value, schemas) From 7736bf168ed00cc3da229ba3d2df72e9e60112fc Mon Sep 17 00:00:00 2001 From: Pierre Fenoll Date: Thu, 2 Dec 2021 14:08:06 +0100 Subject: [PATCH 05/13] use a set type Signed-off-by: Pierre Fenoll --- openapi3gen/openapi3gen.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/openapi3gen/openapi3gen.go b/openapi3gen/openapi3gen.go index 1c233be12..ddc1df694 100644 --- a/openapi3gen/openapi3gen.go +++ b/openapi3gen/openapi3gen.go @@ -68,8 +68,8 @@ type Generator struct { // An OpenAPI identifier has been assigned to each. SchemaRefs map[*openapi3.SchemaRef]int - // ComponentSchemas contains a map of schemas that must be defined in the components, due to cycles - ComponentSchemas map[string]bool + // ComponentSchemaRefs is a set of schemas that must be defined in the components to avoid cycles + ComponentSchemaRefs map[string]struct{} } func NewGenerator(opts ...Option) *Generator { @@ -78,10 +78,10 @@ func NewGenerator(opts ...Option) *Generator { f(gOpt) } return &Generator{ - Types: make(map[reflect.Type]*openapi3.SchemaRef), - SchemaRefs: make(map[*openapi3.SchemaRef]int), - ComponentSchemas: make(map[string]bool), - opts: *gOpt, + Types: make(map[reflect.Type]*openapi3.SchemaRef), + SchemaRefs: make(map[*openapi3.SchemaRef]int), + ComponentSchemaRefs: make(map[string]struct{}), + opts: *gOpt, } } @@ -93,7 +93,7 @@ func (g *Generator) GenerateSchemaRef(t reflect.Type) (*openapi3.SchemaRef, erro func (g *Generator) newSchemaRefForValue(value interface{}, schemas openapi3.Schemas) (*openapi3.SchemaRef, error) { ref, err := g.GenerateSchemaRef(reflect.TypeOf(value)) for ref := range g.SchemaRefs { - if g.ComponentSchemas[ref.Ref] && schemas != nil { + if _, ok := g.ComponentSchemaRefs[ref.Ref]; ok && schemas != nil { schemas[ref.Ref] = &openapi3.SchemaRef{ Value: ref.Value, } @@ -358,7 +358,7 @@ func (g *Generator) generateCycleSchemaRef(t reflect.Type, schema *openapi3.Sche typeName = t.Name() } - g.ComponentSchemas[typeName] = true + g.ComponentSchemaRefs[typeName] = struct{}{} return openapi3.NewSchemaRef(fmt.Sprintf("#/components/schemas/%s", typeName), schema) } From f4cfe1f2113329a1988f6edb08cc834e67c3c177 Mon Sep 17 00:00:00 2001 From: Pierre Fenoll Date: Thu, 2 Dec 2021 14:13:21 +0100 Subject: [PATCH 06/13] check for err Signed-off-by: Pierre Fenoll --- openapi3gen/openapi3gen.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openapi3gen/openapi3gen.go b/openapi3gen/openapi3gen.go index ddc1df694..b993f9eb3 100644 --- a/openapi3gen/openapi3gen.go +++ b/openapi3gen/openapi3gen.go @@ -92,6 +92,9 @@ func (g *Generator) GenerateSchemaRef(t reflect.Type) (*openapi3.SchemaRef, erro func (g *Generator) newSchemaRefForValue(value interface{}, schemas openapi3.Schemas) (*openapi3.SchemaRef, error) { ref, err := g.GenerateSchemaRef(reflect.TypeOf(value)) + if err != nil { + return nil, err + } for ref := range g.SchemaRefs { if _, ok := g.ComponentSchemaRefs[ref.Ref]; ok && schemas != nil { schemas[ref.Ref] = &openapi3.SchemaRef{ From 2c932a452dd9dd241e78a4e2ad55545cac9434dd Mon Sep 17 00:00:00 2001 From: Pierre Fenoll Date: Thu, 2 Dec 2021 14:25:11 +0100 Subject: [PATCH 07/13] check for err Signed-off-by: Pierre Fenoll --- openapi3gen/openapi3gen.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/openapi3gen/openapi3gen.go b/openapi3gen/openapi3gen.go index b993f9eb3..4cb9ec3c5 100644 --- a/openapi3gen/openapi3gen.go +++ b/openapi3gen/openapi3gen.go @@ -107,7 +107,7 @@ func (g *Generator) newSchemaRefForValue(value interface{}, schemas openapi3.Sch ref.Ref = "" } } - return ref, err + return ref, nil } func (g *Generator) generateSchemaRefFor(parents []*jsoninfo.TypeInfo, t reflect.Type, name string, tag reflect.StructTag) (*openapi3.SchemaRef, error) { @@ -116,11 +116,14 @@ func (g *Generator) generateSchemaRefFor(parents []*jsoninfo.TypeInfo, t reflect return ref, nil } ref, err := g.generateWithoutSaving(parents, t, name, tag) + if err != nil { + return nil, err + } if ref != nil { g.Types[t] = ref g.SchemaRefs[ref]++ } - return ref, err + return ref, nil } func getStructField(t reflect.Type, fieldInfo jsoninfo.FieldInfo) reflect.StructField { From fa1b35579c07540321ec66979c43753adaca93a8 Mon Sep 17 00:00:00 2001 From: Pierre Fenoll Date: Thu, 2 Dec 2021 15:03:19 +0100 Subject: [PATCH 08/13] test cycles with option ThrowErrorOnCycle Signed-off-by: Pierre Fenoll --- openapi3gen/openapi3gen_test.go | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/openapi3gen/openapi3gen_test.go b/openapi3gen/openapi3gen_test.go index ee8530c8f..74727d536 100644 --- a/openapi3gen/openapi3gen_test.go +++ b/openapi3gen/openapi3gen_test.go @@ -115,11 +115,33 @@ func TestSimpleStruct(t *testing.T) { } func TestCyclic(t *testing.T) { - g := NewGenerator(ThrowErrorOnCycle()) - schemaRef, err := g.newSchemaRefForValue(&CyclicType0{}, nil) + schemas := make(openapi3.Schemas) + schemaRef, err := NewSchemaRefForValue(&CyclicType0{}, schemas, ThrowErrorOnCycle()) + require.Error(t, err) require.IsType(t, &CycleError{}, err) - require.Nil(t, schemaRef) - require.Empty(t, g.SchemaRefs) + require.Empty(t, schemas) + + schemaRef, err = NewSchemaRefForValue(&CyclicType0{}, schemas) + require.NoError(t, err) + schemaRefForCyclicType0 := &openapi3.SchemaRef{ + Value: &openapi3.Schema{ + Type: "object", + Properties: openapi3.Schemas{ + "a": { + Value: &openapi3.Schema{ + Type: "object", + Properties: openapi3.Schemas{ + "b": {Ref: "#/components/schemas/CyclicType0"}, + }, + }, + }, + }, + }, + } + require.Equal(t, schemaRefForCyclicType0, schemaRef) + require.Equal(t, openapi3.Schemas{ + "CyclicType0": schemaRefForCyclicType0, + }, schemas) } func TestExportedNonTagged(t *testing.T) { From 3cec82294bc4da460149946bea125259149e4b8f Mon Sep 17 00:00:00 2001 From: Pierre Fenoll Date: Thu, 2 Dec 2021 15:18:43 +0100 Subject: [PATCH 09/13] export func (g *Generator) NewSchemaRefForValue(...) so generator fields can be accessed Signed-off-by: Pierre Fenoll --- openapi3gen/openapi3gen.go | 7 +++-- openapi3gen/openapi3gen_test.go | 49 +++++++++++++++++++-------------- 2 files changed, 32 insertions(+), 24 deletions(-) diff --git a/openapi3gen/openapi3gen.go b/openapi3gen/openapi3gen.go index 4cb9ec3c5..07bede031 100644 --- a/openapi3gen/openapi3gen.go +++ b/openapi3gen/openapi3gen.go @@ -52,10 +52,10 @@ func SchemaCustomizer(sc SchemaCustomizerFn) Option { return func(x *generatorOpt) { x.schemaCustomizer = sc } } -// NewSchemaRefForValue uses reflection on the given value to produce a SchemaRef, and updates a supplied map with any dependent component schemas (for cycles) +// NewSchemaRefForValue is a shortcut for NewGenerator(...).NewSchemaRefForValue(...) func NewSchemaRefForValue(value interface{}, schemas openapi3.Schemas, opts ...Option) (*openapi3.SchemaRef, error) { g := NewGenerator(opts...) - return g.newSchemaRefForValue(value, schemas) + return g.NewSchemaRefForValue(value, schemas) } type Generator struct { @@ -90,7 +90,8 @@ func (g *Generator) GenerateSchemaRef(t reflect.Type) (*openapi3.SchemaRef, erro return g.generateSchemaRefFor(nil, t, "_root", "") } -func (g *Generator) newSchemaRefForValue(value interface{}, schemas openapi3.Schemas) (*openapi3.SchemaRef, error) { +// NewSchemaRefForValue uses reflection on the given value to produce a SchemaRef, and updates a supplied map with any dependent component schemas if they lead to cycles +func (g *Generator) NewSchemaRefForValue(value interface{}, schemas openapi3.Schemas) (*openapi3.SchemaRef, error) { ref, err := g.GenerateSchemaRef(reflect.TypeOf(value)) if err != nil { return nil, err diff --git a/openapi3gen/openapi3gen_test.go b/openapi3gen/openapi3gen_test.go index 74727d536..57f9706ae 100644 --- a/openapi3gen/openapi3gen_test.go +++ b/openapi3gen/openapi3gen_test.go @@ -1,4 +1,4 @@ -package openapi3gen +package openapi3gen_test import ( "encoding/json" @@ -10,6 +10,7 @@ import ( "time" "github.com/getkin/kin-openapi/openapi3" + "github.com/getkin/kin-openapi/openapi3gen" "github.com/stretchr/testify/require" ) @@ -46,8 +47,8 @@ func TestSimpleStruct(t *testing.T) { Ptr *SomeOtherType `json:"ptr"` } - g := NewGenerator() - schemaRef, err := g.newSchemaRefForValue(&SomeStruct{}, nil) + g := openapi3gen.NewGenerator() + schemaRef, err := g.NewSchemaRefForValue(&SomeStruct{}, nil) require.NoError(t, err) require.Len(t, g.SchemaRefs, 15) @@ -116,12 +117,12 @@ func TestSimpleStruct(t *testing.T) { func TestCyclic(t *testing.T) { schemas := make(openapi3.Schemas) - schemaRef, err := NewSchemaRefForValue(&CyclicType0{}, schemas, ThrowErrorOnCycle()) + schemaRef, err := openapi3gen.NewSchemaRefForValue(&CyclicType0{}, schemas, openapi3gen.ThrowErrorOnCycle()) require.Error(t, err) - require.IsType(t, &CycleError{}, err) + require.IsType(t, &openapi3gen.CycleError{}, err) require.Empty(t, schemas) - schemaRef, err = NewSchemaRefForValue(&CyclicType0{}, schemas) + schemaRef, err = openapi3gen.NewSchemaRefForValue(&CyclicType0{}, schemas) require.NoError(t, err) schemaRefForCyclicType0 := &openapi3.SchemaRef{ Value: &openapi3.Schema{ @@ -152,7 +153,7 @@ func TestExportedNonTagged(t *testing.T) { EvenAYaml string `yaml:"even_a_yaml"` } - schemaRef, err := NewSchemaRefForValue(&Bla{}, nil, UseAllExportedFields()) + schemaRef, err := openapi3gen.NewSchemaRefForValue(&Bla{}, nil, openapi3gen.UseAllExportedFields()) require.NoError(t, err) require.Equal(t, &openapi3.SchemaRef{Value: &openapi3.Schema{ Type: "object", @@ -168,12 +169,15 @@ func TestExportUint(t *testing.T) { UnsignedInt uint `json:"uint"` } - schemaRef, err := NewSchemaRefForValue(&UnsignedIntStruct{}, nil, UseAllExportedFields()) + schemaRef, err := openapi3gen.NewSchemaRefForValue(&UnsignedIntStruct{}, nil, openapi3gen.UseAllExportedFields()) require.NoError(t, err) require.Equal(t, &openapi3.SchemaRef{Value: &openapi3.Schema{ Type: "object", - Properties: map[string]*openapi3.SchemaRef{ - "uint": {Value: &openapi3.Schema{Type: "integer", Min: &zeroInt}}, + Properties: openapi3.Schemas{ + "uint": {Value: &openapi3.Schema{ + Type: "integer", + Min: openapi3.Float64Ptr(0), + }}, }}}, schemaRef) } @@ -194,7 +198,7 @@ func TestEmbeddedStructs(t *testing.T) { }, } - generator := NewGenerator(UseAllExportedFields()) + generator := openapi3gen.NewGenerator(openapi3gen.UseAllExportedFields()) schemaRef, err := generator.GenerateSchemaRef(reflect.TypeOf(instance)) require.NoError(t, err) @@ -224,7 +228,7 @@ func TestEmbeddedPointerStructs(t *testing.T) { }, } - generator := NewGenerator(UseAllExportedFields()) + generator := openapi3gen.NewGenerator(openapi3gen.UseAllExportedFields()) schemaRef, err := generator.GenerateSchemaRef(reflect.TypeOf(instance)) require.NoError(t, err) @@ -250,7 +254,7 @@ func TestCyclicReferences(t *testing.T) { MapCycle: nil, } - generator := NewGenerator(UseAllExportedFields()) + generator := openapi3gen.NewGenerator(openapi3gen.UseAllExportedFields()) schemaRef, err := generator.GenerateSchemaRef(reflect.TypeOf(instance)) require.NoError(t, err) @@ -287,7 +291,7 @@ func TestSchemaCustomizer(t *testing.T) { EnumField3 string `json:"enum3" myenumtag:"e,f"` } - schemaRef, err := NewSchemaRefForValue(&Bla{}, nil, UseAllExportedFields(), SchemaCustomizer(func(name string, ft reflect.Type, tag reflect.StructTag, schema *openapi3.Schema) error { + customizer := openapi3gen.SchemaCustomizer(func(name string, ft reflect.Type, tag reflect.StructTag, schema *openapi3.Schema) error { t.Logf("Field=%s,Tag=%s", name, tag) if tag.Get("mymintag") != "" { minVal, err := strconv.ParseFloat(tag.Get("mymintag"), 64) @@ -309,8 +313,11 @@ func TestSchemaCustomizer(t *testing.T) { } } return nil - })) + }) + + schemaRef, err := openapi3gen.NewSchemaRefForValue(&Bla{}, nil, openapi3gen.UseAllExportedFields(), customizer) require.NoError(t, err) + jsonSchema, err := json.MarshalIndent(schemaRef, "", " ") require.NoError(t, err) require.JSONEq(t, `{ @@ -358,15 +365,16 @@ func TestSchemaCustomizer(t *testing.T) { } func TestSchemaCustomizerError(t *testing.T) { - type Bla struct{} - _, err := NewSchemaRefForValue(&Bla{}, nil, UseAllExportedFields(), SchemaCustomizer(func(name string, ft reflect.Type, tag reflect.StructTag, schema *openapi3.Schema) error { + customizer := openapi3gen.SchemaCustomizer(func(name string, ft reflect.Type, tag reflect.StructTag, schema *openapi3.Schema) error { return errors.New("test error") - })) + }) + + type Bla struct{} + _, err := openapi3gen.NewSchemaRefForValue(&Bla{}, nil, openapi3gen.UseAllExportedFields(), customizer) require.EqualError(t, err, "test error") } func TestRecursiveSchema(t *testing.T) { - type RecursiveType struct { Field1 string `json:"field1"` Field2 string `json:"field2"` @@ -375,7 +383,7 @@ func TestRecursiveSchema(t *testing.T) { } schemas := make(openapi3.Schemas) - schemaRef, err := NewSchemaRefForValue(&RecursiveType{}, schemas) + schemaRef, err := openapi3gen.NewSchemaRefForValue(&RecursiveType{}, schemas) require.NoError(t, err) jsonSchemas, err := json.MarshalIndent(&schemas, "", " ") @@ -427,5 +435,4 @@ func TestRecursiveSchema(t *testing.T) { }, "type": "object" }`, string(jsonSchemaRef)) - } From 0067f730143178ec37c67689b6aea1b549d7cdfd Mon Sep 17 00:00:00 2001 From: Pierre Fenoll Date: Thu, 2 Dec 2021 16:15:11 +0100 Subject: [PATCH 10/13] examples Signed-off-by: Pierre Fenoll --- openapi3gen/openapi3gen_test.go | 487 ++++++++++++++++++-------------- 1 file changed, 275 insertions(+), 212 deletions(-) diff --git a/openapi3gen/openapi3gen_test.go b/openapi3gen/openapi3gen_test.go index 57f9706ae..0d6d29439 100644 --- a/openapi3gen/openapi3gen_test.go +++ b/openapi3gen/openapi3gen_test.go @@ -3,6 +3,7 @@ package openapi3gen_test import ( "encoding/json" "errors" + "fmt" "reflect" "strconv" "strings" @@ -14,16 +15,8 @@ import ( "github.com/stretchr/testify/require" ) -type CyclicType0 struct { - CyclicField *CyclicType1 `json:"a"` -} -type CyclicType1 struct { - CyclicField *CyclicType0 `json:"b"` -} - -func TestSimpleStruct(t *testing.T) { +func ExampleGenerator_SchemaRefs() { type SomeOtherType string - type SomeStruct struct { Bool bool `json:"bool"` Int int `json:"int"` @@ -49,100 +42,136 @@ func TestSimpleStruct(t *testing.T) { g := openapi3gen.NewGenerator() schemaRef, err := g.NewSchemaRefForValue(&SomeStruct{}, nil) - require.NoError(t, err) - require.Len(t, g.SchemaRefs, 15) - - schemaJSON, err := json.Marshal(schemaRef) - require.NoError(t, err) - - require.JSONEq(t, ` - { - "properties": { - "bool": { - "type": "boolean" - }, - "bytes": { - "format": "byte", - "type": "string" - }, - "float64": { - "format": "double", - "type": "number" - }, - "int": { - "type": "integer" - }, - "int64": { - "format": "int64", - "type": "integer" - }, - "json": {}, - "map": { - "additionalProperties": { - "type": "string" - }, - "type": "object" - }, - "ptr": { - "type": "string" - }, - "slice": { - "items": { - "type": "string" - }, - "type": "array" - }, - "string": { - "type": "string" - }, - "struct": { - "properties": { - "x": { - "type": "string" - } - }, - "type": "object" - }, - "structWithoutFields": {}, - "time": { - "format": "date-time", - "type": "string" - } - }, - "type": "object" - } - `, string(schemaJSON)) + if err != nil { + panic(err) + } + fmt.Printf("g.SchemaRefs: %d\n", len(g.SchemaRefs)) + var data []byte + if data, err = json.MarshalIndent(&schemaRef, "", " "); err != nil { + panic(err) + } + fmt.Printf("schemaRef: %s\n", data) + // Output: + // g.SchemaRefs: 15 + // schemaRef: { + // "properties": { + // "bool": { + // "type": "boolean" + // }, + // "bytes": { + // "format": "byte", + // "type": "string" + // }, + // "float64": { + // "format": "double", + // "type": "number" + // }, + // "int": { + // "type": "integer" + // }, + // "int64": { + // "format": "int64", + // "type": "integer" + // }, + // "json": {}, + // "map": { + // "additionalProperties": { + // "type": "string" + // }, + // "type": "object" + // }, + // "ptr": { + // "type": "string" + // }, + // "slice": { + // "items": { + // "type": "string" + // }, + // "type": "array" + // }, + // "string": { + // "type": "string" + // }, + // "struct": { + // "properties": { + // "x": { + // "type": "string" + // } + // }, + // "type": "object" + // }, + // "structWithoutFields": {}, + // "time": { + // "format": "date-time", + // "type": "string" + // } + // }, + // "type": "object" + // } } -func TestCyclic(t *testing.T) { +func ExampleThrowErrorOnCycle() { + type CyclicType0 struct { + CyclicField *struct { + CyclicField *CyclicType0 `json:"b"` + } `json:"a"` + } + schemas := make(openapi3.Schemas) schemaRef, err := openapi3gen.NewSchemaRefForValue(&CyclicType0{}, schemas, openapi3gen.ThrowErrorOnCycle()) - require.Error(t, err) - require.IsType(t, &openapi3gen.CycleError{}, err) - require.Empty(t, schemas) + if schemaRef != nil || err == nil { + panic(`With option ThrowErrorOnCycle, an error is returned when a schema reference cycle is found`) + } + if _, ok := err.(*openapi3gen.CycleError); !ok { + panic(`With option ThrowErrorOnCycle, an error of type CycleError is returned`) + } + if len(schemas) != 0 { + panic(`No references should have been collected at this point`) + } - schemaRef, err = openapi3gen.NewSchemaRefForValue(&CyclicType0{}, schemas) - require.NoError(t, err) - schemaRefForCyclicType0 := &openapi3.SchemaRef{ - Value: &openapi3.Schema{ - Type: "object", - Properties: openapi3.Schemas{ - "a": { - Value: &openapi3.Schema{ - Type: "object", - Properties: openapi3.Schemas{ - "b": {Ref: "#/components/schemas/CyclicType0"}, - }, - }, - }, - }, - }, + if schemaRef, err = openapi3gen.NewSchemaRefForValue(&CyclicType0{}, schemas); err != nil { + panic(err) + } + + var data []byte + if data, err = json.MarshalIndent(schemaRef, "", " "); err != nil { + panic(err) + } + fmt.Printf("schemaRef: %s\n", data) + if data, err = json.MarshalIndent(schemas, "", " "); err != nil { + panic(err) } - require.Equal(t, schemaRefForCyclicType0, schemaRef) - require.Equal(t, openapi3.Schemas{ - "CyclicType0": schemaRefForCyclicType0, - }, schemas) + fmt.Printf("schemas: %s\n", data) + // Output: + // schemaRef: { + // "properties": { + // "a": { + // "properties": { + // "b": { + // "$ref": "#/components/schemas/CyclicType0" + // } + // }, + // "type": "object" + // } + // }, + // "type": "object" + // } + // schemas: { + // "CyclicType0": { + // "properties": { + // "a": { + // "properties": { + // "b": { + // "$ref": "#/components/schemas/CyclicType0" + // } + // }, + // "type": "object" + // } + // }, + // "type": "object" + // } + // } } func TestExportedNonTagged(t *testing.T) { @@ -164,24 +193,34 @@ func TestExportedNonTagged(t *testing.T) { }}}, schemaRef) } -func TestExportUint(t *testing.T) { +func ExampleUseAllExportedFields() { type UnsignedIntStruct struct { UnsignedInt uint `json:"uint"` } schemaRef, err := openapi3gen.NewSchemaRefForValue(&UnsignedIntStruct{}, nil, openapi3gen.UseAllExportedFields()) - require.NoError(t, err) - require.Equal(t, &openapi3.SchemaRef{Value: &openapi3.Schema{ - Type: "object", - Properties: openapi3.Schemas{ - "uint": {Value: &openapi3.Schema{ - Type: "integer", - Min: openapi3.Float64Ptr(0), - }}, - }}}, schemaRef) + if err != nil { + panic(err) + } + + var data []byte + if data, err = json.MarshalIndent(schemaRef, "", " "); err != nil { + panic(err) + } + fmt.Printf("schemaRef: %s\n", data) + // Output: + // schemaRef: { + // "properties": { + // "uint": { + // "minimum": 0, + // "type": "integer" + // } + // }, + // "type": "object" + // } } -func TestEmbeddedStructs(t *testing.T) { +func ExampleGenerateSchemaRef() { type EmbeddedStruct struct { ID string } @@ -201,14 +240,28 @@ func TestEmbeddedStructs(t *testing.T) { generator := openapi3gen.NewGenerator(openapi3gen.UseAllExportedFields()) schemaRef, err := generator.GenerateSchemaRef(reflect.TypeOf(instance)) - require.NoError(t, err) - - var ok bool - _, ok = schemaRef.Value.Properties["Name"] - require.Equal(t, true, ok) + if err != nil { + panic(err) + } - _, ok = schemaRef.Value.Properties["ID"] - require.Equal(t, true, ok) + var data []byte + if data, err = json.MarshalIndent(schemaRef.Value.Properties["Name"].Value, "", " "); err != nil { + panic(err) + } + fmt.Printf(`schemaRef.Value.Properties["Name"].Value: %s`, data) + fmt.Println() + if data, err = json.MarshalIndent(schemaRef.Value.Properties["ID"].Value, "", " "); err != nil { + panic(err) + } + fmt.Printf(`schemaRef.Value.Properties["ID"].Value: %s`, data) + fmt.Println() + // Output: + // schemaRef.Value.Properties["Name"].Value: { + // "type": "string" + // } + // schemaRef.Value.Properties["ID"].Value: { + // "type": "string" + // } } func TestEmbeddedPointerStructs(t *testing.T) { @@ -271,7 +324,7 @@ func TestCyclicReferences(t *testing.T) { require.Equal(t, "#/components/schemas/ObjectDiff", schemaRef.Value.Properties["MapCycle"].Value.AdditionalProperties.Ref) } -func TestSchemaCustomizer(t *testing.T) { +func ExampleSchemaCustomizer() { type NestedInnerBla struct { Enum1Field string `json:"enum1" myenumtag:"a,b"` } @@ -292,7 +345,6 @@ func TestSchemaCustomizer(t *testing.T) { } customizer := openapi3gen.SchemaCustomizer(func(name string, ft reflect.Type, tag reflect.StructTag, schema *openapi3.Schema) error { - t.Logf("Field=%s,Tag=%s", name, tag) if tag.Get("mymintag") != "" { minVal, err := strconv.ParseFloat(tag.Get("mymintag"), 64) if err != nil { @@ -316,52 +368,58 @@ func TestSchemaCustomizer(t *testing.T) { }) schemaRef, err := openapi3gen.NewSchemaRefForValue(&Bla{}, nil, openapi3gen.UseAllExportedFields(), customizer) - require.NoError(t, err) + if err != nil { + panic(err) + } - jsonSchema, err := json.MarshalIndent(schemaRef, "", " ") - require.NoError(t, err) - require.JSONEq(t, `{ - "properties": { - "AnonStruct": { - "properties": { - "InnerFieldWithTag": { - "maximum": 50, - "minimum": -1, - "type": "integer" - }, - "InnerFieldWithoutTag": { - "type": "integer" - }, - "enum1": { - "enum": [ - "a", - "b" - ], - "type": "string" - } - }, - "type": "object" - }, - "UntaggedStringField": { - "type": "string" - }, - "enum2": { - "enum": [ - "c", - "d" - ], - "type": "string" - }, - "enum3": { - "enum": [ - "e", - "f" - ], - "type": "string" - } - }, - "type": "object" -}`, string(jsonSchema)) + var data []byte + if data, err = json.MarshalIndent(schemaRef, "", " "); err != nil { + panic(err) + } + fmt.Printf("schemaRef: %s\n", data) + // Output: + // schemaRef: { + // "properties": { + // "AnonStruct": { + // "properties": { + // "InnerFieldWithTag": { + // "maximum": 50, + // "minimum": -1, + // "type": "integer" + // }, + // "InnerFieldWithoutTag": { + // "type": "integer" + // }, + // "enum1": { + // "enum": [ + // "a", + // "b" + // ], + // "type": "string" + // } + // }, + // "type": "object" + // }, + // "UntaggedStringField": { + // "type": "string" + // }, + // "enum2": { + // "enum": [ + // "c", + // "d" + // ], + // "type": "string" + // }, + // "enum3": { + // "enum": [ + // "e", + // "f" + // ], + // "type": "string" + // } + // }, + // "type": "object" + // } } func TestSchemaCustomizerError(t *testing.T) { @@ -374,7 +432,7 @@ func TestSchemaCustomizerError(t *testing.T) { require.EqualError(t, err, "test error") } -func TestRecursiveSchema(t *testing.T) { +func ExampleNewSchemaRefForValue_recursive() { type RecursiveType struct { Field1 string `json:"field1"` Field2 string `json:"field2"` @@ -384,55 +442,60 @@ func TestRecursiveSchema(t *testing.T) { schemas := make(openapi3.Schemas) schemaRef, err := openapi3gen.NewSchemaRefForValue(&RecursiveType{}, schemas) - require.NoError(t, err) - - jsonSchemas, err := json.MarshalIndent(&schemas, "", " ") - require.NoError(t, err) - - jsonSchemaRef, err := json.MarshalIndent(&schemaRef, "", " ") - require.NoError(t, err) + if err != nil { + panic(err) + } - require.JSONEq(t, `{ - "RecursiveType": { - "properties": { - "children": { - "items": { - "$ref": "#/components/schemas/RecursiveType" - }, - "type": "array" - }, - "field1": { - "type": "string" - }, - "field2": { - "type": "string" - }, - "field3": { - "type": "string" - } - }, - "type": "object" - } - }`, string(jsonSchemas)) - - require.JSONEq(t, `{ - "properties": { - "children": { - "items": { - "$ref": "#/components/schemas/RecursiveType" - }, - "type": "array" - }, - "field1": { - "type": "string" - }, - "field2": { - "type": "string" - }, - "field3": { - "type": "string" - } - }, - "type": "object" - }`, string(jsonSchemaRef)) + var data []byte + if data, err = json.MarshalIndent(&schemas, "", " "); err != nil { + panic(err) + } + fmt.Printf("schemas: %s\n", data) + if data, err = json.MarshalIndent(&schemaRef, "", " "); err != nil { + panic(err) + } + fmt.Printf("schemaRef: %s\n", data) + // Output: + // schemas: { + // "RecursiveType": { + // "properties": { + // "children": { + // "items": { + // "$ref": "#/components/schemas/RecursiveType" + // }, + // "type": "array" + // }, + // "field1": { + // "type": "string" + // }, + // "field2": { + // "type": "string" + // }, + // "field3": { + // "type": "string" + // } + // }, + // "type": "object" + // } + // } + // schemaRef: { + // "properties": { + // "children": { + // "items": { + // "$ref": "#/components/schemas/RecursiveType" + // }, + // "type": "array" + // }, + // "field1": { + // "type": "string" + // }, + // "field2": { + // "type": "string" + // }, + // "field3": { + // "type": "string" + // } + // }, + // "type": "object" + // } } From e83f32de2317c86fb817bb040ba5cb0179bd433e Mon Sep 17 00:00:00 2001 From: Pierre Fenoll Date: Thu, 2 Dec 2021 16:19:57 +0100 Subject: [PATCH 11/13] README.md Signed-off-by: Pierre Fenoll --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 92e7fad89..abefc2f48 100644 --- a/README.md +++ b/README.md @@ -193,6 +193,11 @@ func arrayUniqueItemsChecker(items []interface{}) bool { ## Sub-v0 breaking API changes +### v0.84.0 +* The prototype of `openapi3gen.NewSchemaRefForValue` changed: + * It no longer returns a map but that is still accessible under the field `(*Generator).SchemaRefs`. + * It now takes in an additional argument (basically `doc.Components.Schemas`) which gets written to so `$ref` cycles can be properly handled. + ### v0.61.0 * Renamed `openapi2.Swagger` to `openapi2.T`. * Renamed `openapi2conv.FromV3Swagger` to `openapi2conv.FromV3`. From 290eee702573d72ef5a65ed7cf13f82aee461f52 Mon Sep 17 00:00:00 2001 From: Pierre Fenoll Date: Thu, 2 Dec 2021 16:21:30 +0100 Subject: [PATCH 12/13] unexport (*Generator)ComponentSchemaRefs Signed-off-by: Pierre Fenoll --- openapi3gen/openapi3gen.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/openapi3gen/openapi3gen.go b/openapi3gen/openapi3gen.go index 07bede031..45577bce0 100644 --- a/openapi3gen/openapi3gen.go +++ b/openapi3gen/openapi3gen.go @@ -68,8 +68,8 @@ type Generator struct { // An OpenAPI identifier has been assigned to each. SchemaRefs map[*openapi3.SchemaRef]int - // ComponentSchemaRefs is a set of schemas that must be defined in the components to avoid cycles - ComponentSchemaRefs map[string]struct{} + // componentSchemaRefs is a set of schemas that must be defined in the components to avoid cycles + componentSchemaRefs map[string]struct{} } func NewGenerator(opts ...Option) *Generator { @@ -80,7 +80,7 @@ func NewGenerator(opts ...Option) *Generator { return &Generator{ Types: make(map[reflect.Type]*openapi3.SchemaRef), SchemaRefs: make(map[*openapi3.SchemaRef]int), - ComponentSchemaRefs: make(map[string]struct{}), + componentSchemaRefs: make(map[string]struct{}), opts: *gOpt, } } @@ -97,7 +97,7 @@ func (g *Generator) NewSchemaRefForValue(value interface{}, schemas openapi3.Sch return nil, err } for ref := range g.SchemaRefs { - if _, ok := g.ComponentSchemaRefs[ref.Ref]; ok && schemas != nil { + if _, ok := g.componentSchemaRefs[ref.Ref]; ok && schemas != nil { schemas[ref.Ref] = &openapi3.SchemaRef{ Value: ref.Value, } @@ -365,7 +365,7 @@ func (g *Generator) generateCycleSchemaRef(t reflect.Type, schema *openapi3.Sche typeName = t.Name() } - g.ComponentSchemaRefs[typeName] = struct{}{} + g.componentSchemaRefs[typeName] = struct{}{} return openapi3.NewSchemaRef(fmt.Sprintf("#/components/schemas/%s", typeName), schema) } From 8e075ef6f6d4396a06148c01ebfd856d7765186d Mon Sep 17 00:00:00 2001 From: Pierre Fenoll Date: Thu, 2 Dec 2021 16:28:42 +0100 Subject: [PATCH 13/13] thanks go vet ./... Signed-off-by: Pierre Fenoll --- openapi3gen/openapi3gen_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openapi3gen/openapi3gen_test.go b/openapi3gen/openapi3gen_test.go index 0d6d29439..a6d1620e6 100644 --- a/openapi3gen/openapi3gen_test.go +++ b/openapi3gen/openapi3gen_test.go @@ -220,7 +220,7 @@ func ExampleUseAllExportedFields() { // } } -func ExampleGenerateSchemaRef() { +func ExampleGenerator_GenerateSchemaRef() { type EmbeddedStruct struct { ID string }