From 10bfd795a7e3e5f0d449a7340a9b4c4e95573b35 Mon Sep 17 00:00:00 2001 From: Khoirun Nawa Date: Fri, 10 Mar 2023 12:54:34 +0700 Subject: [PATCH] support multidimensional array for more general types (#77) --- definition_builder.go | 43 +++++++++++++++++++++++------------ definition_builder_test.go | 46 ++++++++++++++++++++++++++++++++++---- 2 files changed, 71 insertions(+), 18 deletions(-) diff --git a/definition_builder.go b/definition_builder.go index eeb9f13..440beec 100755 --- a/definition_builder.go +++ b/definition_builder.go @@ -80,9 +80,9 @@ func (b definitionBuilder) addModel(st reflect.Type, nameOverride string) *spec. // fixes issue 77 but feels like a workaround. if b.isPrimitiveType(modelName, st.Kind()) { if isArray { - sm.Type = []string{"array"} - sm.Items = &spec.SchemaOrArray{Schema: &spec.Schema{ - SchemaProps: spec.SchemaProps{Type: []string{jsonSchemaType(st.Kind().String())}}}} + /* sm.Type = []string{"array"} + sm.Items = &spec.SchemaOrArray{Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{Type: []string{jsonSchemaType(st.Kind().String())}}}}*/ } } @@ -313,26 +313,41 @@ func (b definitionBuilder) buildArrayTypeProperty(field reflect.StructField, jso prop.Type = []string{stringt} return jsonName, prop } - var pType = "array" - prop.Type = []string{pType} - isPrimitive := b.isPrimitiveType(fieldType.Elem().Name(), fieldType.Elem().Kind()) - elemTypeName := b.getElementTypeName(modelName, jsonName, fieldType.Elem()) prop.Items = &spec.SchemaOrArray{ Schema: &spec.Schema{}, } + itemSchema := &prop + itemType := fieldType + isArray := b.isSliceOrArrayType(fieldType.Kind()) + for isArray { + itemType = itemType.Elem() + isArray = b.isSliceOrArrayType(itemType.Kind()) + if itemType.Kind() == reflect.Uint8 { + stringt := "string" + itemSchema.Type = []string{stringt} + return jsonName, prop + } + itemSchema.Items = &spec.SchemaOrArray{ + Schema: &spec.Schema{}, + } + itemSchema.Type = []string{"array"} + itemSchema = itemSchema.Items.Schema + } + isPrimitive := b.isPrimitiveType(itemType.Name(), itemType.Kind()) + elemTypeName := b.getElementTypeName(modelName, jsonName, itemType) if isPrimitive { - mapped := b.jsonSchemaType(elemTypeName, fieldType.Elem().Kind()) - prop.Items.Schema.Type = []string{mapped} - prop.Items.Schema.Format = b.jsonSchemaFormat(elemTypeName, fieldType.Elem().Kind()) + mapped := b.jsonSchemaType(elemTypeName, itemType.Kind()) + itemSchema.Type = []string{mapped} + itemSchema.Format = b.jsonSchemaFormat(elemTypeName, itemType.Kind()) } else { - prop.Items.Schema.Ref = spec.MustCreateRef("#/definitions/" + elemTypeName) + itemSchema.Ref = spec.MustCreateRef("#/definitions/" + elemTypeName) } // add|overwrite model for element type - if fieldType.Elem().Kind() == reflect.Ptr { - fieldType = fieldType.Elem() + if itemType.Kind() == reflect.Ptr { + itemType = itemType.Elem() } if !isPrimitive { - b.addModel(fieldType.Elem(), elemTypeName) + b.addModel(itemType, elemTypeName) } return jsonName, prop } diff --git a/definition_builder_test.go b/definition_builder_test.go index 2cc15a9..899bf41 100644 --- a/definition_builder_test.go +++ b/definition_builder_test.go @@ -440,7 +440,11 @@ type email struct { func TestDoubleByteArray(t *testing.T) { db := definitionBuilder{Definitions: spec.Definitions{}, Config: Config{}} db.addModelFrom(email{}) - sc, ok := db.Definitions["restfulspec.email.attachments"] + scParent, ok := db.Definitions["restfulspec.email"] + if !ok { + t.Fail() + } + sc, ok := scParent.Properties["attachments"] if !ok { t.Fail() } @@ -457,17 +461,51 @@ type matrix struct { func TestDoubleStringArray(t *testing.T) { db := definitionBuilder{Definitions: spec.Definitions{}, Config: Config{}} db.addModelFrom(matrix{}) - sc, ok := db.Definitions["restfulspec.matrix.Cells"] + scParent, ok := db.Definitions["restfulspec.matrix"] if !ok { t.Log(db.Definitions) t.Fail() } - t.Log(sc) + sc, ok := scParent.Properties["Cells"] + if !ok { + t.Log(db.Definitions) + t.Fail() + } + t.Logf("%+v", sc) if got, want := sc.Type[0], "array"; got != want { t.Errorf("got [%v:%T] want [%v:%T]", got, got, want, want) } tp := sc.Items.Schema.Type - t.Log(tp) + t.Logf("%+v", tp) +} + +type Cell struct { + Value string +} + +type DoubleStructArray struct { + Cells [][]Cell +} + +func TestDoubleStructArray(t *testing.T) { + db := definitionBuilder{Definitions: spec.Definitions{}, Config: Config{}} + db.addModelFrom(DoubleStructArray{}) + + schema, ok := db.Definitions["restfulspec.DoubleStructArray"] + if !ok { + t.Logf("definitions: %v", db.Definitions) + t.Fail() + } + t.Logf("%+v", schema) + if want, got := schema.Properties["Cells"].Type[0], "array"; got != want { + t.Errorf("got [%v:%T] want [%v:%T]", got, got, want, want) + } + if want, got := schema.Properties["Cells"].Items.Schema.Type[0], "array"; got != want { + t.Errorf("got [%v:%T] want [%v:%T]", got, got, want, want) + } + if want, got := schema.Properties["Cells"].Items.Schema.Items.Schema.Ref.String(), "#/definitions/restfulspec.Cell"; got != want { + t.Errorf("got [%v:%T] want [%v:%T]", got, got, want, want) + } } type childPostBuildSwaggerSchema struct {