plugin/kubernetes: Enable protobuf, Update client api package (#1114)

* vendor

* code
This commit is contained in:
Chris O'Haver
2017-09-29 15:58:50 -04:00
committed by John Belamaric
parent 45b0252c1a
commit 4b3a430ff2
1511 changed files with 286873 additions and 253612 deletions

View File

@@ -0,0 +1,4 @@
language: go
go:
- 1.x

View File

@@ -1,5 +1,8 @@
Change history of swagger
=
2017-01-30
- moved from go-restful/swagger to go-restful-swagger12
2015-10-16
- add type override mechanism for swagger models (MR 254, nathanejohnson)
- replace uses of wildcard in generated apidocs (issue 251)

View File

@@ -0,0 +1,22 @@
Copyright (c) 2017 Ernest Micklei
MIT License
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -1,3 +1,8 @@
# go-restful-swagger12
[![Build Status](https://travis-ci.org/emicklei/go-restful-swagger12.png)](https://travis-ci.org/emicklei/go-restful-swagger12)
[![GoDoc](https://godoc.org/github.com/emicklei/go-restful-swagger12?status.svg)](https://godoc.org/github.com/emicklei/go-restful-swagger12)
How to use Swagger UI with go-restful
=
@@ -74,3 +79,5 @@ Notes
--
- The Nickname of an Operation is automatically set by finding the name of the function. You can override it using RouteBuilder.Operation(..)
- The WebServices field of swagger.Config can be used to control which service you want to expose and document ; you can have multiple configs and therefore multiple endpoints.
© 2017, ernestmicklei.com. MIT License. Contributions welcome.

View File

@@ -2,6 +2,7 @@ package swagger
import (
"net/http"
"reflect"
"github.com/emicklei/go-restful"
)
@@ -9,6 +10,13 @@ import (
// PostBuildDeclarationMapFunc can be used to modify the api declaration map.
type PostBuildDeclarationMapFunc func(apiDeclarationMap *ApiDeclarationList)
// MapSchemaFormatFunc can be used to modify typeName at definition time.
type MapSchemaFormatFunc func(typeName string) string
// MapModelTypeNameFunc can be used to return the desired typeName for a given
// type. It will return false if the default name should be used.
type MapModelTypeNameFunc func(t reflect.Type) (string, bool)
type Config struct {
// url where the services are available, e.g. http://localhost:8080
// if left empty then the basePath of Swagger is taken from the actual request
@@ -31,4 +39,8 @@ type Config struct {
PostBuildHandler PostBuildDeclarationMapFunc
// Swagger global info struct
Info Info
// [optional] If set, model builder should call this handler to get addition typename-to-swagger-format-field conversion.
SchemaFormatHandler MapSchemaFormatFunc
// [optional] If set, model builder should call this handler to retrieve the name for a given type.
ModelTypeNameHandler MapModelTypeNameFunc
}

View File

@@ -14,6 +14,7 @@ type ModelBuildable interface {
type modelBuilder struct {
Models *ModelList
Config *Config
}
type documentable interface {
@@ -42,6 +43,12 @@ func (b modelBuilder) addModelFrom(sample interface{}) {
}
func (b modelBuilder) addModel(st reflect.Type, nameOverride string) *Model {
// Turn pointers into simpler types so further checks are
// correct.
if st.Kind() == reflect.Ptr {
st = st.Elem()
}
modelName := b.keyFrom(st)
if nameOverride != "" {
modelName = nameOverride
@@ -50,6 +57,14 @@ func (b modelBuilder) addModel(st reflect.Type, nameOverride string) *Model {
if b.isPrimitiveType(modelName) {
return nil
}
// golang encoding/json packages says array and slice values encode as
// JSON arrays, except that []byte encodes as a base64-encoded string.
// If we see a []byte here, treat it at as a primitive type (string)
// and deal with it in buildArrayTypeProperty.
if (st.Kind() == reflect.Slice || st.Kind() == reflect.Array) &&
st.Elem().Kind() == reflect.Uint8 {
return nil
}
// see if we already have visited this model
if _, ok := b.Models.At(modelName); ok {
return nil
@@ -128,6 +143,11 @@ func (b modelBuilder) buildProperty(field reflect.StructField, model *Model, mod
return "", "", prop
}
if field.Name == "XMLName" && field.Type.String() == "xml.Name" {
// property is metadata for the xml.Name attribute, can be skipped
return "", "", prop
}
if tag := field.Tag.Get("modelDescription"); tag != "" {
modelDescription = tag
}
@@ -146,7 +166,7 @@ func (b modelBuilder) buildProperty(field reflect.StructField, model *Model, mod
prop.Type = &pType
}
if prop.Format == "" {
prop.Format = b.jsonSchemaFormat(fieldType.String())
prop.Format = b.jsonSchemaFormat(b.keyFrom(fieldType))
}
return jsonName, modelDescription, prop
}
@@ -178,18 +198,19 @@ func (b modelBuilder) buildProperty(field reflect.StructField, model *Model, mod
return jsonName, modelDescription, prop
case fieldKind == reflect.Map:
// if it's a map, it's unstructured, and swagger 1.2 can't handle it
anyt := "any"
prop.Type = &anyt
objectType := "object"
prop.Type = &objectType
return jsonName, modelDescription, prop
}
if b.isPrimitiveType(fieldType.String()) {
mapped := b.jsonSchemaType(fieldType.String())
fieldTypeName := b.keyFrom(fieldType)
if b.isPrimitiveType(fieldTypeName) {
mapped := b.jsonSchemaType(fieldTypeName)
prop.Type = &mapped
prop.Format = b.jsonSchemaFormat(fieldType.String())
prop.Format = b.jsonSchemaFormat(fieldTypeName)
return jsonName, modelDescription, prop
}
modelType := fieldType.String()
modelType := b.keyFrom(fieldType)
prop.Ref = &modelType
if fieldType.Name() == "" { // override type of anonymous structs
@@ -231,7 +252,7 @@ func (b modelBuilder) buildStructTypeProperty(field reflect.StructField, jsonNam
if field.Name == fieldType.Name() && field.Anonymous && !hasNamedJSONTag(field) {
// embedded struct
sub := modelBuilder{new(ModelList)}
sub := modelBuilder{new(ModelList), b.Config}
sub.addModel(fieldType, "")
subKey := sub.keyFrom(fieldType)
// merge properties from sub
@@ -263,7 +284,7 @@ func (b modelBuilder) buildStructTypeProperty(field reflect.StructField, jsonNam
}
// simple struct
b.addModel(fieldType, "")
var pType = fieldType.String()
var pType = b.keyFrom(fieldType)
prop.Ref = &pType
return jsonName, prop
}
@@ -275,11 +296,17 @@ func (b modelBuilder) buildArrayTypeProperty(field reflect.StructField, jsonName
return jsonName, prop
}
fieldType := field.Type
if fieldType.Elem().Kind() == reflect.Uint8 {
stringt := "string"
prop.Type = &stringt
return jsonName, prop
}
var pType = "array"
prop.Type = &pType
isPrimitive := b.isPrimitiveType(fieldType.Elem().Name())
elemTypeName := b.getElementTypeName(modelName, jsonName, fieldType.Elem())
prop.Items = new(Item)
if b.isPrimitiveType(elemTypeName) {
if isPrimitive {
mapped := b.jsonSchemaType(elemTypeName)
prop.Items.Type = &mapped
} else {
@@ -289,7 +316,9 @@ func (b modelBuilder) buildArrayTypeProperty(field reflect.StructField, jsonName
if fieldType.Elem().Kind() == reflect.Ptr {
fieldType = fieldType.Elem()
}
b.addModel(fieldType.Elem(), elemTypeName)
if !isPrimitive {
b.addModel(fieldType.Elem(), elemTypeName)
}
return jsonName, prop
}
@@ -305,16 +334,25 @@ func (b modelBuilder) buildPointerTypeProperty(field reflect.StructField, jsonNa
if fieldType.Elem().Kind() == reflect.Slice || fieldType.Elem().Kind() == reflect.Array {
var pType = "array"
prop.Type = &pType
isPrimitive := b.isPrimitiveType(fieldType.Elem().Elem().Name())
elemName := b.getElementTypeName(modelName, jsonName, fieldType.Elem().Elem())
prop.Items = &Item{Ref: &elemName}
// add|overwrite model for element type
b.addModel(fieldType.Elem().Elem(), elemName)
if isPrimitive {
primName := b.jsonSchemaType(elemName)
prop.Items = &Item{Ref: &primName}
} else {
prop.Items = &Item{Ref: &elemName}
}
if !isPrimitive {
// add|overwrite model for element type
b.addModel(fieldType.Elem().Elem(), elemName)
}
} else {
// non-array, pointer type
var pType = b.jsonSchemaType(fieldType.String()[1:]) // no star, include pkg path
if b.isPrimitiveType(fieldType.String()[1:]) {
fieldTypeName := b.keyFrom(fieldType.Elem())
var pType = b.jsonSchemaType(fieldTypeName) // no star, include pkg path
if b.isPrimitiveType(fieldTypeName) {
prop.Type = &pType
prop.Format = b.jsonSchemaFormat(fieldType.String()[1:])
prop.Format = b.jsonSchemaFormat(fieldTypeName)
return jsonName, prop
}
prop.Ref = &pType
@@ -330,19 +368,21 @@ func (b modelBuilder) buildPointerTypeProperty(field reflect.StructField, jsonNa
func (b modelBuilder) getElementTypeName(modelName, jsonName string, t reflect.Type) string {
if t.Kind() == reflect.Ptr {
return t.String()[1:]
t = t.Elem()
}
if t.Name() == "" {
return modelName + "." + jsonName
}
if b.isPrimitiveType(t.Name()) {
return b.jsonSchemaType(t.Name())
}
return b.keyFrom(t)
}
func (b modelBuilder) keyFrom(st reflect.Type) string {
key := st.String()
if b.Config != nil && b.Config.ModelTypeNameHandler != nil {
if name, ok := b.Config.ModelTypeNameHandler(st); ok {
key = name
}
}
if len(st.Name()) == 0 { // unnamed type
// Swagger UI has special meaning for [
key = strings.Replace(key, "[]", "||", -1)
@@ -352,6 +392,9 @@ func (b modelBuilder) keyFrom(st reflect.Type) string {
// see also https://golang.org/ref/spec#Numeric_types
func (b modelBuilder) isPrimitiveType(modelName string) bool {
if len(modelName) == 0 {
return false
}
return strings.Contains("uint uint8 uint16 uint32 uint64 int int8 int16 int32 int64 float32 float64 bool string byte rune time.Time", modelName)
}
@@ -399,6 +442,11 @@ func (b modelBuilder) jsonSchemaType(modelName string) string {
}
func (b modelBuilder) jsonSchemaFormat(modelName string) string {
if b.Config != nil && b.Config.SchemaFormatHandler != nil {
if mapped := b.Config.SchemaFormatHandler(modelName); mapped != "" {
return mapped
}
}
schemaMap := map[string]string{
"int": "int32",
"int32": "int32",

View File

@@ -1,7 +1,9 @@
package swagger
import (
"encoding/xml"
"net"
"reflect"
"testing"
"time"
)
@@ -38,6 +40,59 @@ func TestRef_Issue190(t *testing.T) {
}`)
}
func TestWithoutAdditionalFormat(t *testing.T) {
type mytime struct {
time.Time
}
type usemytime struct {
t mytime
}
testJsonFromStruct(t, usemytime{}, `{
"swagger.usemytime": {
"id": "swagger.usemytime",
"required": [
"t"
],
"properties": {
"t": {
"type": "string"
}
}
}
}`)
}
func TestWithAdditionalFormat(t *testing.T) {
type mytime struct {
time.Time
}
type usemytime struct {
t mytime
}
testJsonFromStructWithConfig(t, usemytime{}, `{
"swagger.usemytime": {
"id": "swagger.usemytime",
"required": [
"t"
],
"properties": {
"t": {
"type": "string",
"format": "date-time"
}
}
}
}`, &Config{
SchemaFormatHandler: func(typeName string) string {
switch typeName {
case "swagger.mytime":
return "date-time"
}
return ""
},
})
}
// clear && go test -v -test.run TestCustomMarshaller_Issue96 ...swagger
func TestCustomMarshaller_Issue96(t *testing.T) {
type Vote struct {
@@ -803,8 +858,8 @@ type Region struct {
// clear && go test -v -test.run TestRegion_Issue113 ...swagger
func TestRegion_Issue113(t *testing.T) {
testJsonFromStruct(t, []Region{}, `{
"integer": {
"id": "integer",
"||swagger.Region": {
"id": "||swagger.Region",
"properties": {}
},
"swagger.Region": {
@@ -816,10 +871,7 @@ func TestRegion_Issue113(t *testing.T) {
],
"properties": {
"id": {
"type": "array",
"items": {
"$ref": "integer"
}
"type": "string"
},
"name": {
"type": "string"
@@ -828,10 +880,6 @@ func TestRegion_Issue113(t *testing.T) {
"type": "string"
}
}
},
"||swagger.Region": {
"id": "||swagger.Region",
"properties": {}
}
}`)
}
@@ -874,6 +922,25 @@ func TestIssue158(t *testing.T) {
testJsonFromStruct(t, Customer{}, expected)
}
func TestPointers(t *testing.T) {
type Vote struct {
What YesNo
}
testJsonFromStruct(t, &Vote{}, `{
"swagger.Vote": {
"id": "swagger.Vote",
"required": [
"What"
],
"properties": {
"What": {
"type": "string"
}
}
}
}`)
}
func TestSlices(t *testing.T) {
type Address struct {
Country string `json:"country,omitempty"`
@@ -1140,3 +1207,77 @@ func TestOverridenTypeTagE1(t *testing.T) {
`
testJsonFromStruct(t, E{}, expected)
}
type XmlNamed struct {
XMLName xml.Name `xml:"user"`
Id string `json:"id" xml:"id"`
Name string `json:"name" xml:"name"`
}
func TestXmlNameStructs(t *testing.T) {
expected := `
{
"swagger.XmlNamed": {
"id": "swagger.XmlNamed",
"required": [
"id",
"name"
],
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
}
}
}
}
`
testJsonFromStruct(t, XmlNamed{}, expected)
}
func TestNameCustomization(t *testing.T) {
expected := `
{
"swagger.A": {
"id": "swagger.A",
"description": "A struct",
"required": [
"SB"
],
"properties": {
"SB": {
"type": "string",
"description": "SB field"
},
"metadata": {
"$ref": "new.swagger.SpecialC1",
"description": "C1 field"
}
}
},
"new.swagger.SpecialC1": {
"id": "new.swagger.SpecialC1",
"description": "C1 struct",
"required": [
"SC"
],
"properties": {
"SC": {
"type": "string",
"description": "SC field"
}
}
}
}`
testJsonFromStructWithConfig(t, A{}, expected, &Config{
ModelTypeNameHandler: func(t reflect.Type) (string, bool) {
if t == reflect.TypeOf(C1{}) {
return "new.swagger.SpecialC1", true
}
return "", false
},
})
}

View File

@@ -33,6 +33,21 @@ func (prop *ModelProperty) setMaximum(field reflect.StructField) {
func (prop *ModelProperty) setType(field reflect.StructField) {
if tag := field.Tag.Get("type"); tag != "" {
// Check if the first two characters of the type tag are
// intended to emulate slice/array behaviour.
//
// If type is intended to be a slice/array then add the
// overriden type to the array item instead of the main property
if len(tag) > 2 && tag[0:2] == "[]" {
pType := "array"
prop.Type = &pType
prop.Items = new(Item)
iType := tag[2:]
prop.Items.Type = &iType
return
}
prop.Type = &tag
}
}

View File

@@ -8,14 +8,16 @@ import (
// clear && go test -v -test.run TestThatExtraTagsAreReadIntoModel ...swagger
func TestThatExtraTagsAreReadIntoModel(t *testing.T) {
type fakeint int
type fakearray string
type Anything struct {
Name string `description:"name" modelDescription:"a test"`
Size int `minimum:"0" maximum:"10"`
Stati string `enum:"off|on" default:"on" modelDescription:"more description"`
ID string `unique:"true"`
FakeInt fakeint `type:"integer"`
IP net.IP `type:"string"`
Password string
Name string `description:"name" modelDescription:"a test"`
Size int `minimum:"0" maximum:"10"`
Stati string `enum:"off|on" default:"on" modelDescription:"more description"`
ID string `unique:"true"`
FakeInt fakeint `type:"integer"`
FakeArray fakearray `type:"[]string"`
IP net.IP `type:"string"`
Password string
}
m := modelsFromStruct(Anything{})
props, _ := m.At("swagger.Anything")
@@ -49,8 +51,16 @@ func TestThatExtraTagsAreReadIntoModel(t *testing.T) {
if got, want := *p6.Type, "integer"; got != want {
t.Errorf("got %v want %v", got, want)
}
p7, _ := props.Properties.At("IP")
if got, want := *p7.Type, "string"; got != want {
p7, _ := props.Properties.At("FakeArray")
if got, want := *p7.Type, "array"; got != want {
t.Errorf("got %v want %v", got, want)
}
p7p, _ := props.Properties.At("FakeArray")
if got, want := *p7p.Items.Type, "string"; got != want {
t.Errorf("got %v want %v", got, want)
}
p8, _ := props.Properties.At("IP")
if got, want := *p8.Type, "string"; got != want {
t.Errorf("got %v want %v", got, want)
}

View File

@@ -118,6 +118,7 @@ type ApiDeclaration struct {
ApiVersion string `json:"apiVersion"`
BasePath string `json:"basePath"`
ResourcePath string `json:"resourcePath"` // must start with /
Info Info `json:"info"`
Apis []Api `json:"apis,omitempty"`
Models ModelList `json:"models,omitempty"`
Produces []string `json:"produces,omitempty"`

View File

@@ -5,7 +5,7 @@ import (
"testing"
"github.com/emicklei/go-restful"
"github.com/emicklei/go-restful/swagger/test_package"
"github.com/emicklei/go-restful-swagger12/test_package"
)
func TestInfoStruct_Issue231(t *testing.T) {
@@ -157,6 +157,53 @@ func TestWriteSamples(t *testing.T) {
}`)
}
func TestRoutesWithCommonPart(t *testing.T) {
ws1 := new(restful.WebService)
ws1.Path("/")
ws1.Route(ws1.GET("/foobar").To(dummy).Writes(test_package.TestStruct{}))
ws1.Route(ws1.HEAD("/foobar").To(dummy).Writes(test_package.TestStruct{}))
ws1.Route(ws1.GET("/foo").To(dummy).Writes([]test_package.TestStruct{}))
ws1.Route(ws1.HEAD("/foo").To(dummy).Writes(test_package.TestStruct{}))
cfg := Config{
WebServicesUrl: "http://here.com",
ApiPath: "/apipath",
WebServices: []*restful.WebService{ws1},
}
sws := newSwaggerService(cfg)
decl := sws.composeDeclaration(ws1, "/foo")
str, err := json.MarshalIndent(decl.Apis, "", " ")
if err != nil {
t.Fatal(err)
}
compareJson(t, string(str), `[
{
"path": "/foo",
"description": "",
"operations": [
{
"type": "array",
"items": {
"$ref": "test_package.TestStruct"
},
"method": "GET",
"nickname": "dummy",
"parameters": []
},
{
"type": "test_package.TestStruct",
"method": "HEAD",
"nickname": "dummy",
"parameters": []
}
]
}
]`)
}
// go test -v -test.run TestServiceToApi ...swagger
func TestServiceToApi(t *testing.T) {
ws := new(restful.WebService)
@@ -226,25 +273,12 @@ func TestComposeResponseMessages(t *testing.T) {
route := restful.Route{ResponseErrors: responseErrors}
decl := new(ApiDeclaration)
decl.Models = ModelList{}
msgs := composeResponseMessages(route, decl)
msgs := composeResponseMessages(route, decl, &Config{})
if msgs[0].ResponseModel != "swagger.TestItem" {
t.Errorf("got %s want swagger.TestItem", msgs[0].ResponseModel)
}
}
// clear && go test -v -test.run TestComposeResponseMessageArray ...swagger
func TestComposeResponseMessageArray(t *testing.T) {
responseErrors := map[int]restful.ResponseError{}
responseErrors[400] = restful.ResponseError{Code: 400, Message: "Bad Request", Model: []TestItem{}}
route := restful.Route{ResponseErrors: responseErrors}
decl := new(ApiDeclaration)
decl.Models = ModelList{}
msgs := composeResponseMessages(route, decl)
if msgs[0].ResponseModel != "array[swagger.TestItem]" {
t.Errorf("got %s want swagger.TestItem", msgs[0].ResponseModel)
}
}
func TestIssue78(t *testing.T) {
sws := newSwaggerService(Config{})
models := new(ModelList)

View File

@@ -226,6 +226,9 @@ func (sws SwaggerService) composeDeclaration(ws *restful.WebService, pathPrefix
pathToRoutes := newOrderedRouteMap()
for _, other := range ws.Routes() {
if strings.HasPrefix(other.Path, pathPrefix) {
if len(pathPrefix) > 1 && len(other.Path) > len(pathPrefix) && other.Path[len(pathPrefix)] != '/' {
continue
}
pathToRoutes.Add(other.Path, other)
}
}
@@ -241,7 +244,7 @@ func (sws SwaggerService) composeDeclaration(ws *restful.WebService, pathPrefix
DataTypeFields: DataTypeFields{Type: &voidString},
Parameters: []Parameter{},
Nickname: route.Operation,
ResponseMessages: composeResponseMessages(route, &decl)}
ResponseMessages: composeResponseMessages(route, &decl, &sws.config)}
operation.Consumes = route.Consumes
operation.Produces = route.Produces
@@ -271,13 +274,13 @@ func withoutWildcard(path string) string {
}
// composeResponseMessages takes the ResponseErrors (if any) and creates ResponseMessages from them.
func composeResponseMessages(route restful.Route, decl *ApiDeclaration) (messages []ResponseMessage) {
func composeResponseMessages(route restful.Route, decl *ApiDeclaration, config *Config) (messages []ResponseMessage) {
if route.ResponseErrors == nil {
return messages
}
// sort by code
codes := sort.IntSlice{}
for code, _ := range route.ResponseErrors {
for code := range route.ResponseErrors {
codes = append(codes, code)
}
codes.Sort()
@@ -290,13 +293,12 @@ func composeResponseMessages(route restful.Route, decl *ApiDeclaration) (message
if each.Model != nil {
st := reflect.TypeOf(each.Model)
isCollection, st := detectCollectionType(st)
modelName := modelBuilder{}.keyFrom(st)
if isCollection {
modelName = "array[" + modelName + "]"
// collection cannot be in responsemodel
if !isCollection {
modelName := modelBuilder{}.keyFrom(st)
modelBuilder{Models: &decl.Models, Config: config}.addModel(st, "")
message.ResponseModel = modelName
}
modelBuilder{&decl.Models}.addModel(st, "")
// reference the model
message.ResponseModel = modelName
}
messages = append(messages, message)
}
@@ -331,12 +333,13 @@ func detectCollectionType(st reflect.Type) (bool, reflect.Type) {
// addModelFromSample creates and adds (or overwrites) a Model from a sample resource
func (sws SwaggerService) addModelFromSampleTo(operation *Operation, isResponse bool, sample interface{}, models *ModelList) {
mb := modelBuilder{Models: models, Config: &sws.config}
if isResponse {
type_, items := asDataType(sample)
operation.Type = type_
sampleType, items := asDataType(sample, &sws.config)
operation.Type = sampleType
operation.Items = items
}
modelBuilder{models}.addModelFrom(sample)
mb.addModelFrom(sample)
}
func asSwaggerParameter(param restful.ParameterData) Parameter {
@@ -411,7 +414,7 @@ func asParamType(kind int) string {
return ""
}
func asDataType(any interface{}) (*string, *Item) {
func asDataType(any interface{}, config *Config) (*string, *Item) {
// If it's not a collection, return the suggested model name
st := reflect.TypeOf(any)
isCollection, st := detectCollectionType(st)
@@ -424,7 +427,7 @@ func asDataType(any interface{}) (*string, *Item) {
// XXX: This is not very elegant
// We create an Item object referring to the given model
models := ModelList{}
mb := modelBuilder{&models}
mb := modelBuilder{Models: &models, Config: config}
mb.addModelFrom(any)
elemTypeName := mb.getElementTypeName(modelName, "", st)

View File

@@ -9,19 +9,27 @@ import (
"testing"
)
func testJsonFromStruct(t *testing.T, sample interface{}, expectedJson string) bool {
m := modelsFromStruct(sample)
func testJsonFromStructWithConfig(t *testing.T, sample interface{}, expectedJson string, config *Config) bool {
m := modelsFromStructWithConfig(sample, config)
data, _ := json.MarshalIndent(m, " ", " ")
return compareJson(t, string(data), expectedJson)
}
func modelsFromStruct(sample interface{}) *ModelList {
func modelsFromStructWithConfig(sample interface{}, config *Config) *ModelList {
models := new(ModelList)
builder := modelBuilder{models}
builder := modelBuilder{Models: models, Config: config}
builder.addModelFrom(sample)
return models
}
func testJsonFromStruct(t *testing.T, sample interface{}, expectedJson string) bool {
return testJsonFromStructWithConfig(t, sample, expectedJson, &Config{})
}
func modelsFromStruct(sample interface{}) *ModelList {
return modelsFromStructWithConfig(sample, &Config{})
}
func compareJson(t *testing.T, actualJsonAsString string, expectedJsonAsString string) bool {
success := false
var actualMap map[string]interface{}
@@ -35,7 +43,7 @@ func compareJson(t *testing.T, actualJsonAsString string, expectedJsonAsString s
err := json.Unmarshal([]byte(expectedJsonAsString), &expectedArray)
success = reflect.DeepEqual(actualArray, expectedArray)
if err != nil {
t.Fatalf("Unparsable expected JSON: %s", err)
t.Fatalf("Unparsable expected JSON: %s, actual: %v, expected: %v", err, actualJsonAsString, expectedJsonAsString)
}
} else {
success = reflect.DeepEqual(actualMap, expectedMap)