Skip to content

Commit

Permalink
Override deep-level fields in request body object
Browse files Browse the repository at this point in the history
  • Loading branch information
philipchan-nautiluscapital committed May 25, 2020
1 parent d8a6d4a commit 3f54376
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 31 deletions.
43 changes: 12 additions & 31 deletions operation.go
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand All @@ -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
}
Expand All @@ -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
}
Expand Down Expand Up @@ -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
}
Expand All @@ -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
}
Expand All @@ -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
}
Expand Down Expand Up @@ -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
}
Expand Down
97 changes: 97 additions & 0 deletions operation_test.go
Expand Up @@ -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()
Expand Down Expand Up @@ -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()
Expand Down

0 comments on commit 3f54376

Please sign in to comment.