From 4e7b01fe32a921ce50afbf11d88b26d3e5162024 Mon Sep 17 00:00:00 2001 From: DerekStrickland Date: Tue, 27 Jul 2021 10:56:35 -0400 Subject: [PATCH 1/2] Detect if a field is anonymous and handle the indirection --- openapi3gen/openapi3gen.go | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/openapi3gen/openapi3gen.go b/openapi3gen/openapi3gen.go index 960698324..84d1f998d 100644 --- a/openapi3gen/openapi3gen.go +++ b/openapi3gen/openapi3gen.go @@ -217,9 +217,21 @@ func (g *Generator) generateWithoutSaving(parents []*jsoninfo.TypeInfo, t reflec // If asked, try to use yaml tag name, fType := fieldInfo.JSONName, fieldInfo.Type if !fieldInfo.HasJSONTag && g.opts.useAllExportedFields { - ff := t.Field(fieldInfo.Index[len(fieldInfo.Index)-1]) - if tag, ok := ff.Tag.Lookup("yaml"); ok && tag != "-" { - name, fType = tag, ff.Type + // Handle anonymous fields/embedded structs + if t.Field(fieldInfo.Index[0]).Anonymous { + ref, err := g.generateSchemaRefFor(parents, fType) + if err != nil { + return nil, err + } + if ref != nil { + g.SchemaRefs[ref]++ + schema.WithPropertyRef(name, ref) + } + } else { + ff := t.Field(fieldInfo.Index[len(fieldInfo.Index)-1]) + if tag, ok := ff.Tag.Lookup("yaml"); ok && tag != "-" { + name, fType = tag, ff.Type + } } } From 5e49b036ea84401add56c9daca5a14c1e7ee7f65 Mon Sep 17 00:00:00 2001 From: DerekStrickland Date: Wed, 28 Jul 2021 10:25:23 -0400 Subject: [PATCH 2/2] Added unit test for embedded structs --- openapi3gen/openapi3gen_test.go | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/openapi3gen/openapi3gen_test.go b/openapi3gen/openapi3gen_test.go index 777bb9dad..f8e2430e2 100644 --- a/openapi3gen/openapi3gen_test.go +++ b/openapi3gen/openapi3gen_test.go @@ -1,6 +1,7 @@ package openapi3gen import ( + "reflect" "testing" "github.com/getkin/kin-openapi/openapi3" @@ -53,3 +54,33 @@ func TestExportUint(t *testing.T) { "uint": {Value: &openapi3.Schema{Type: "integer", Min: &zeroInt}}, }}}, schemaRef) } + +func TestEmbeddedStructs(t *testing.T) { + type EmbeddedStruct struct { + ID string + } + + type ContainerStruct struct { + Name string + EmbeddedStruct + } + + instance := &ContainerStruct{ + Name: "Container", + EmbeddedStruct: EmbeddedStruct{ + ID: "Embedded", + }, + } + + generator := NewGenerator(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) + + _, ok = schemaRef.Value.Properties["ID"] + require.Equal(t, true, ok) +}