Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support maps and slices in operations #14

Merged
merged 1 commit into from
Oct 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions builders.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,14 @@ func (b *baseBuilder) writeNotEmpty(indent int, format string, s string) {
func (b *baseBuilder) writeDataType(indent int, f Field) {
dataTypeDef, found := b.swagger.dataTypeDefFor(f)
if !found {
ts := "(no type)"
if f.Type != nil {
ts = f.Type.String()
}
panic(fmt.Sprintf("No dataTypeDef defined for kind %s, type %s. You should either change the type, "+
"or add a custom data type mapper. See Representing Custom Types at "+
"https://godoc.org/github.com/rgalanakis/sashay#hdr-Sashay_Detail__Representing_Custom_Types "+
"for more information.", f.Kind.String(), f.Type.String()))
"for more information.", f.Kind.String(), ts))
}
objectFields := ObjectFields{}
dataTypeDef.DataTyper(f, objectFields)
Expand Down Expand Up @@ -107,7 +111,7 @@ func (b *baseBuilder) writeRefSchema(indent int, f Field) {
} else {
b.writeLn(indent, "$ref: '%s'", schemaRefLink(f))
}
} else {
} else if f.Kind != reflect.Invalid {
b.writeDataType(indent, f)
}
}
Expand Down Expand Up @@ -252,6 +256,18 @@ func (b *pathBuilder) writePaths() {
}

func (b *pathBuilder) writeParams(indent int, f Field) {
if f.Kind != reflect.Struct {
b.base.writeLn(indent, "requestBody:")
b.base.writeLn(indent+1, "content:")
b.base.writeLn(indent+2, "*/*:")
b.base.writeLn(indent+3, "schema:")
if f.Kind == reflect.Map {
b.base.writeLn(indent+4, "type: object")
} else if f.Kind == reflect.Slice {
b.base.writeLn(indent+4, "type: array")
}
return
}
writeParams := b.base.writeOnce(indent, "parameters:")
for _, field := range enumerateStructFields(f) {
tag := field.StructField.Tag
Expand Down
4 changes: 4 additions & 0 deletions data_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ func BuiltinDataTyperFor(value interface{}, chained ...DataTyper) DataTyper {
dt = SimpleDataTyper("number", "float")
case time.Time, *time.Time:
dt = SimpleDataTyper("string", "date-time")
case map[string]interface{}:
dt = SimpleDataTyper("object", "")
case []interface{}, []map[string]interface{}:
dt = SimpleDataTyper("array", "")
}
typers := []DataTyper{dt, defaultDataTyper}
typers = append(typers, chained...)
Expand Down
14 changes: 13 additions & 1 deletion sashay.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,19 @@ func New(title, description, version string) *Sashay {
// BuiltinDataTypeValues is a slice of values of all supported data types.
// Use it for when you want to define custom DataTypers for the builtin types,
// like if you are parsing validations.
var BuiltinDataTypeValues = []interface{}{int(0), int64(0), int32(0), "", false, float64(0), float32(0), time.Time{}}
var BuiltinDataTypeValues = []interface{}{
int(0),
int64(0),
int32(0),
"",
false,
float64(0),
float32(0),
time.Time{},
make(map[string]interface{}, 0),
make([]map[string]interface{}, 0),
make([]interface{}, 0),
}

// Add registers a Swagger operations and all the associated types.
func (sa *Sashay) Add(op Operation) Operation {
Expand Down
101 changes: 101 additions & 0 deletions sashay_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1284,4 +1284,105 @@ paths:
contents, err := ioutil.ReadFile(f.Name())
Expect(string(contents)).To(ContainSubstring("SwaggerGenAPI"))
})

It("can handle maps", func() {
sw.Add(sashay.NewOperation(
"GET",
"/users",
"",
map[string]interface{}{},
map[string]interface{}{},
map[string]interface{}{},
))
Expect(sw.BuildYAML()).To(ContainSubstring(`paths:
/users:
get:
operationId: getUsers
requestBody:
content:
*/*:
schema:
type: object
responses:
'200':
description: ok response
content:
application/json:
schema:
type: object
'default':
description: error response
content:
application/json:
schema:
type: object`))
})
It("can handle interface slices", func() {
sw.Add(sashay.NewOperation(
"GET",
"/users",
"",
[]interface{}{},
[]interface{}{},
[]interface{}{},
))
Expect(sw.BuildYAML()).To(ContainSubstring(`paths:
/users:
get:
operationId: getUsers
requestBody:
content:
*/*:
schema:
type: array
responses:
'200':
description: ok response
content:
application/json:
schema:
type: array
items:
'default':
description: error response
content:
application/json:
schema:
type: array
items:`))
})
It("can handle subtypes of maps", func() {
type submap map[string]interface{}
sw.DefineDataType(submap{}, sashay.SimpleDataTyper("object", ""))
sw.Add(sashay.NewOperation(
"GET",
"/users",
"",
submap{},
submap{},
submap{},
))
Expect(sw.BuildYAML()).To(ContainSubstring(`paths:
/users:
get:
operationId: getUsers
requestBody:
content:
*/*:
schema:
type: object
responses:
'200':
description: ok response
content:
application/json:
schema:
type: object
'default':
description: error response
content:
application/json:
schema:
type: object`))
})
})