diff --git a/operation.go b/operation.go index d7f82129c..32f2d0218 100644 --- a/operation.go +++ b/operation.go @@ -253,33 +253,14 @@ func (operation *Operation) ParseParamComment(commentLine string, astFile *ast.F case "primitive": param.Schema.Type = spec.StringOrArray{refType} case "array": - param.Schema.Type = spec.StringOrArray{objectType} - param.Schema.Items = &spec.SchemaOrArray{ - Schema: &spec.Schema{ - SchemaProps: spec.SchemaProps{}, - }, - } - // Array of Primitive or Object - if IsPrimitiveType(refType) { - param.Schema.Items.Schema.Type = spec.StringOrArray{refType} - } else { - refType, typeSpec, err := operation.registerSchemaType(refType, astFile) - if err != nil { - return err - } - param.Schema.Items.Schema.Ref = spec.Ref{ - Ref: jsonreference.MustCreateRef("#/definitions/" + TypeDocName(refType, typeSpec)), - } - } + refType = "[]" + refType + fallthrough case "object": - refType, typeSpec, err := operation.registerSchemaType(refType, astFile) + schema, err := operation.parseObjectSchema(refType, astFile) if err != nil { return err } - param.Schema.Type = []string{} - param.Schema.Ref = spec.Ref{ - Ref: jsonreference.MustCreateRef("#/definitions/" + TypeDocName(refType, typeSpec)), - } + param.Schema = schema } default: return fmt.Errorf("%s is not supported paramType", paramType) @@ -635,7 +616,7 @@ var responsePattern = regexp.MustCompile(`([\d]+)[\s]+([\w\{\}]+)[\s]+([\w\-\.\/ //RepsonseType{data1=Type1,data2=Type2} var combinedPattern = regexp.MustCompile(`^([\w\-\.\/\[\]]+)\{(.*)\}$`) -func (operation *Operation) parseResponseObjectSchema(refType string, astFile *ast.File) (*spec.Schema, error) { +func (operation *Operation) parseObjectSchema(refType string, astFile *ast.File) (*spec.Schema, error) { switch { case refType == "interface{}": return &spec.Schema{SchemaProps: spec.SchemaProps{Type: []string{"object"}}}, nil @@ -645,7 +626,7 @@ func (operation *Operation) parseResponseObjectSchema(refType string, astFile *a case IsPrimitiveType(refType): return &spec.Schema{SchemaProps: spec.SchemaProps{Type: []string{refType}}}, nil case strings.HasPrefix(refType, "[]"): - schema, err := operation.parseResponseObjectSchema(refType[2:], astFile) + schema, err := operation.parseObjectSchema(refType[2:], astFile) if err != nil { return nil, err } @@ -664,7 +645,7 @@ func (operation *Operation) parseResponseObjectSchema(refType string, astFile *a if refType == "interface{}" { valueSchema.Allows = true } else { - schema, err := operation.parseResponseObjectSchema(refType, astFile) + schema, err := operation.parseObjectSchema(refType, astFile) if err != nil { return &spec.Schema{}, err } @@ -698,7 +679,7 @@ func (operation *Operation) parseResponseCombinedObjectSchema(refType string, as return nil, fmt.Errorf("invalid type: %s", refType) } refType = matches[1] - schema, err := operation.parseResponseObjectSchema(refType, astFile) + schema, err := operation.parseObjectSchema(refType, astFile) if err != nil { return nil, err } @@ -722,7 +703,7 @@ func (operation *Operation) parseResponseCombinedObjectSchema(refType string, as for _, field := range fields { if matches := strings.SplitN(field, "=", 2); len(matches) == 2 { if strings.HasPrefix(matches[1], "[]") { - itemSchema, err := operation.parseResponseObjectSchema(matches[1][2:], astFile) + itemSchema, err := operation.parseObjectSchema(matches[1][2:], astFile) if err != nil { return nil, err } @@ -731,7 +712,7 @@ func (operation *Operation) parseResponseCombinedObjectSchema(refType string, as Items: &spec.SchemaOrArray{Schema: itemSchema}}, } } else { - schema, err := operation.parseResponseObjectSchema(matches[1], astFile) + schema, err := operation.parseObjectSchema(matches[1], astFile) if err != nil { return nil, err } @@ -762,12 +743,12 @@ func (operation *Operation) parseResponseSchema(schemaType, refType string, astF switch schemaType { case "object": if !strings.HasPrefix(refType, "[]") { - return operation.parseResponseObjectSchema(refType, astFile) + return operation.parseObjectSchema(refType, astFile) } refType = refType[2:] fallthrough case "array": - schema, err := operation.parseResponseObjectSchema(refType, astFile) + schema, err := operation.parseObjectSchema(refType, astFile) if err != nil { return nil, err } diff --git a/operation_test.go b/operation_test.go index 1367ecdb4..29f3a2c6c 100644 --- a/operation_test.go +++ b/operation_test.go @@ -938,6 +938,53 @@ func TestParseParamCommentByBodyType(t *testing.T) { assert.Equal(t, expected, string(b)) } +func TestParseParamCommentByBodyTypeWithDeepNestedFields(t *testing.T) { + comment := `@Param body body model.CommonHeader{data=string,data2=int} true "test deep"` + operation := NewOperation() + operation.parser = New() + + operation.parser.TypeDefinitions["model"] = make(map[string]*ast.TypeSpec) + operation.parser.TypeDefinitions["model"]["CommonHeader"] = &ast.TypeSpec{} + + err := operation.ParseComment(comment, nil) + assert.NoError(t, err) + assert.Len(t, operation.Parameters, 1) + assert.Equal(t, "test deep", operation.Parameters[0].Description) + assert.True(t, operation.Parameters[0].Required) + + b, err := json.MarshalIndent(operation, "", " ") + assert.NoError(t, err) + expected := `{ + "parameters": [ + { + "description": "test deep", + "name": "body", + "in": "body", + "required": true, + "schema": { + "allOf": [ + { + "$ref": "#/definitions/model.CommonHeader" + }, + { + "type": "object", + "properties": { + "data": { + "type": "string" + }, + "data2": { + "type": "integer" + } + } + } + ] + } + } + ] +}` + assert.Equal(t, expected, string(b)) +} + func TestParseParamCommentByBodyTypeArrayOfPrimitiveGo(t *testing.T) { comment := `@Param some_id body []int true "Some ID"` operation := NewOperation() @@ -965,6 +1012,56 @@ func TestParseParamCommentByBodyTypeArrayOfPrimitiveGo(t *testing.T) { assert.Equal(t, expected, string(b)) } +func TestParseParamCommentByBodyTypeArrayOfPrimitiveGoWithDeepNestedFields(t *testing.T) { + comment := `@Param body body []model.CommonHeader{data=string,data2=int} true "test deep"` + operation := NewOperation() + operation.parser = New() + + operation.parser.TypeDefinitions["model"] = make(map[string]*ast.TypeSpec) + operation.parser.TypeDefinitions["model"]["CommonHeader"] = &ast.TypeSpec{} + + err := operation.ParseComment(comment, nil) + assert.NoError(t, err) + assert.Len(t, operation.Parameters, 1) + assert.Equal(t, "test deep", operation.Parameters[0].Description) + assert.True(t, operation.Parameters[0].Required) + + b, err := json.MarshalIndent(operation, "", " ") + assert.NoError(t, err) + expected := `{ + "parameters": [ + { + "description": "test deep", + "name": "body", + "in": "body", + "required": true, + "schema": { + "type": "array", + "items": { + "allOf": [ + { + "$ref": "#/definitions/model.CommonHeader" + }, + { + "type": "object", + "properties": { + "data": { + "type": "string" + }, + "data2": { + "type": "integer" + } + } + } + ] + } + } + } + ] +}` + assert.Equal(t, expected, string(b)) +} + func TestParseParamCommentByBodyTypeErr(t *testing.T) { comment := `@Param some_id body model.OrderRow true "Some ID"` operation := NewOperation()