From f4cc084070f5af89a733052b61a139b9b7f80d7d Mon Sep 17 00:00:00 2001 From: Bogdan Ungureanu Date: Wed, 17 Jul 2019 15:24:33 +0300 Subject: [PATCH 1/5] fix issue #397: Unnecessary type field on response objects --- example/basic/docs/docs.go | 43 ++++++++++++++++++++----- example/basic/docs/swagger/swagger.json | 6 ---- example/basic/docs/swagger/swagger.yaml | 6 ---- operation.go | 2 +- operation_test.go | 2 -- parser_test.go | 22 ------------- testdata/composition/expected.json | 5 --- testdata/simple2/docs/docs.go | 12 ++----- testdata/simple3/docs/docs.go | 12 ++----- 9 files changed, 42 insertions(+), 68 deletions(-) diff --git a/example/basic/docs/docs.go b/example/basic/docs/docs.go index c94e6b300..d6e005b55 100644 --- a/example/basic/docs/docs.go +++ b/example/basic/docs/docs.go @@ -1,14 +1,19 @@ // GENERATED BY THE COMMAND ABOVE; DO NOT EDIT // This file was generated by swaggo/swag at -// 2018-06-14 10:58:52.298729546 +0800 CST m=+0.030701430 +// 2019-07-17 15:09:52.573759118 +0300 EEST m=+0.033526900 package docs import ( + "bytes" + "encoding/json" + + "github.com/alecthomas/template" "github.com/swaggo/swag" ) var doc = `{ + "schemes": {{ marshal .Schemes }}, "swagger": "2.0", "info": { "description": "This is a sample server Petstore server.", @@ -58,14 +63,12 @@ var doc = `{ "400": { "description": "We need ID!!", "schema": { - "type": "object", "$ref": "#/definitions/web.APIError" } }, "404": { "description": "Can not find ID", "schema": { - "type": "object", "$ref": "#/definitions/web.APIError" } } @@ -112,14 +115,12 @@ var doc = `{ "400": { "description": "We need ID!!", "schema": { - "type": "object", "$ref": "#/definitions/web.APIError" } }, "404": { "description": "Can not find ID", "schema": { - "type": "object", "$ref": "#/definitions/web.APIError" } } @@ -169,14 +170,12 @@ var doc = `{ "400": { "description": "We need ID!!", "schema": { - "type": "object", "$ref": "#/definitions/web.APIError" } }, "404": { "description": "Can not find ID", "schema": { - "type": "object", "$ref": "#/definitions/web.APIError" } } @@ -264,11 +263,39 @@ var doc = `{ } }` +type swaggerInfo struct { + Version string + Host string + BasePath string + Schemes []string + Title string + Description string +} + +// SwaggerInfo holds exported Swagger Info so clients can modify it +var SwaggerInfo = swaggerInfo{ Schemes: []string{}} + type s struct{} func (s *s) ReadDoc() string { - return doc + t, err := template.New("swagger_info").Funcs(template.FuncMap{ + "marshal": func(v interface {}) string { + a, _ := json.Marshal(v) + return string(a) + }, + }).Parse(doc) + if err != nil { + return doc + } + + var tpl bytes.Buffer + if err := t.Execute(&tpl, SwaggerInfo); err != nil { + return doc + } + + return tpl.String() } + func init() { swag.Register(swag.Name, &s{}) } diff --git a/example/basic/docs/swagger/swagger.json b/example/basic/docs/swagger/swagger.json index 3c0d40bce..a482a190a 100644 --- a/example/basic/docs/swagger/swagger.json +++ b/example/basic/docs/swagger/swagger.json @@ -48,14 +48,12 @@ "400": { "description": "We need ID!!", "schema": { - "type": "object", "$ref": "#/definitions/web.APIError" } }, "404": { "description": "Can not find ID", "schema": { - "type": "object", "$ref": "#/definitions/web.APIError" } } @@ -102,14 +100,12 @@ "400": { "description": "We need ID!!", "schema": { - "type": "object", "$ref": "#/definitions/web.APIError" } }, "404": { "description": "Can not find ID", "schema": { - "type": "object", "$ref": "#/definitions/web.APIError" } } @@ -159,14 +155,12 @@ "400": { "description": "We need ID!!", "schema": { - "type": "object", "$ref": "#/definitions/web.APIError" } }, "404": { "description": "Can not find ID", "schema": { - "type": "object", "$ref": "#/definitions/web.APIError" } } diff --git a/example/basic/docs/swagger/swagger.yaml b/example/basic/docs/swagger/swagger.yaml index c524bce76..7df7527bd 100644 --- a/example/basic/docs/swagger/swagger.yaml +++ b/example/basic/docs/swagger/swagger.yaml @@ -86,12 +86,10 @@ paths: description: We need ID!! schema: $ref: '#/definitions/web.APIError' - type: object "404": description: Can not find ID schema: $ref: '#/definitions/web.APIError' - type: object summary: Upload file /testapi/get-string-by-int/{some_id}: get: @@ -123,12 +121,10 @@ paths: description: We need ID!! schema: $ref: '#/definitions/web.APIError' - type: object "404": description: Can not find ID schema: $ref: '#/definitions/web.APIError' - type: object summary: Add a new pet to the store /testapi/get-struct-array-by-string/{some_id}: get: @@ -163,10 +159,8 @@ paths: description: We need ID!! schema: $ref: '#/definitions/web.APIError' - type: object "404": description: Can not find ID schema: $ref: '#/definitions/web.APIError' - type: object swagger: "2.0" diff --git a/operation.go b/operation.go index 0f4661e9a..289105ef6 100644 --- a/operation.go +++ b/operation.go @@ -542,10 +542,10 @@ func (operation *Operation) ParseResponseComment(commentLine string, astFile *as } // so we have to know all type in app - //TODO: we might omitted schema.type if schemaType equals 'object' response.Schema = &spec.Schema{SchemaProps: spec.SchemaProps{Type: []string{schemaType}}} if schemaType == "object" { + response.Schema.SchemaProps = spec.SchemaProps{} response.Schema.Ref = spec.Ref{ Ref: jsonreference.MustCreateRef("#/definitions/" + refType), } diff --git a/operation_test.go b/operation_test.go index 3564f8dd5..0e2b9477b 100644 --- a/operation_test.go +++ b/operation_test.go @@ -141,7 +141,6 @@ func TestParseResponseCommentWithObjectType(t *testing.T) { response := operation.Responses.StatusCodeResponses[200] assert.Equal(t, `Error message, if code != 200`, response.Description) - assert.Equal(t, spec.StringOrArray{"object"}, response.Schema.Type) b, _ := json.MarshalIndent(operation, "", " ") @@ -150,7 +149,6 @@ func TestParseResponseCommentWithObjectType(t *testing.T) { "200": { "description": "Error message, if code != 200", "schema": { - "type": "object", "$ref": "#/definitions/model.OrderRow" } } diff --git a/parser_test.go b/parser_test.go index 65ac9f79d..9eae95de7 100644 --- a/parser_test.go +++ b/parser_test.go @@ -338,7 +338,6 @@ func TestParseSimpleApi1(t *testing.T) { "400": { "description": "We need ID!!", "schema": { - "type": "object", "$ref": "#/definitions/web.APIError" } }, @@ -354,7 +353,6 @@ func TestParseSimpleApi1(t *testing.T) { "404": { "description": "Can not find ID", "schema": { - "type": "object", "$ref": "#/definitions/web.APIError" } } @@ -402,14 +400,12 @@ func TestParseSimpleApi1(t *testing.T) { "400": { "description": "We need ID!!", "schema": { - "type": "object", "$ref": "#/definitions/web.APIError" } }, "404": { "description": "Can not find ID", "schema": { - "type": "object", "$ref": "#/definitions/web.APIError" } } @@ -514,14 +510,12 @@ func TestParseSimpleApi1(t *testing.T) { "400": { "description": "We need ID!!", "schema": { - "type": "object", "$ref": "#/definitions/web.APIError" } }, "404": { "description": "Can not find ID", "schema": { - "type": "object", "$ref": "#/definitions/web.APIError" } } @@ -980,14 +974,12 @@ func TestParseSimpleApi_ForSnakecase(t *testing.T) { "400": { "description": "We need ID!!", "schema": { - "type": "object", "$ref": "#/definitions/web.APIError" } }, "404": { "description": "Can not find ID", "schema": { - "type": "object", "$ref": "#/definitions/web.APIError" } } @@ -1035,14 +1027,12 @@ func TestParseSimpleApi_ForSnakecase(t *testing.T) { "400": { "description": "We need ID!!", "schema": { - "type": "object", "$ref": "#/definitions/web.APIError" } }, "404": { "description": "Can not find ID", "schema": { - "type": "object", "$ref": "#/definitions/web.APIError" } } @@ -1147,14 +1137,12 @@ func TestParseSimpleApi_ForSnakecase(t *testing.T) { "400": { "description": "We need ID!!", "schema": { - "type": "object", "$ref": "#/definitions/web.APIError" } }, "404": { "description": "Can not find ID", "schema": { - "type": "object", "$ref": "#/definitions/web.APIError" } } @@ -1470,14 +1458,12 @@ func TestParseSimpleApi_ForLowerCamelcase(t *testing.T) { "400": { "description": "We need ID!!", "schema": { - "type": "object", "$ref": "#/definitions/web.APIError" } }, "404": { "description": "Can not find ID", "schema": { - "type": "object", "$ref": "#/definitions/web.APIError" } } @@ -1525,14 +1511,12 @@ func TestParseSimpleApi_ForLowerCamelcase(t *testing.T) { "400": { "description": "We need ID!!", "schema": { - "type": "object", "$ref": "#/definitions/web.APIError" } }, "404": { "description": "Can not find ID", "schema": { - "type": "object", "$ref": "#/definitions/web.APIError" } } @@ -1637,14 +1621,12 @@ func TestParseSimpleApi_ForLowerCamelcase(t *testing.T) { "400": { "description": "We need ID!!", "schema": { - "type": "object", "$ref": "#/definitions/web.APIError" } }, "404": { "description": "Can not find ID", "schema": { - "type": "object", "$ref": "#/definitions/web.APIError" } } @@ -1924,14 +1906,12 @@ func TestParseStructComment(t *testing.T) { "400": { "description": "We need ID!!", "schema": { - "type": "object", "$ref": "#/definitions/web.APIError" } }, "404": { "description": "Can not find ID", "schema": { - "type": "object", "$ref": "#/definitions/web.APIError" } } @@ -2112,7 +2092,6 @@ func TestParseModelNotUnderRoot(t *testing.T) { "200": { "description": "ok", "schema": { - "type": "object", "$ref": "#/definitions/data.Foo" } } @@ -2223,7 +2202,6 @@ func TestParseModelAsTypeAlias(t *testing.T) { "200": { "description": "ok", "schema": { - "type": "object", "$ref": "#/definitions/data.TimeContainer" } } diff --git a/testdata/composition/expected.json b/testdata/composition/expected.json index cbe396623..efb7b081c 100644 --- a/testdata/composition/expected.json +++ b/testdata/composition/expected.json @@ -25,7 +25,6 @@ "200": { "description": "OK", "schema": { - "type": "object", "$ref": "#/definitions/api.Bar" } } @@ -46,7 +45,6 @@ "200": { "description": "OK", "schema": { - "type": "object", "$ref": "#/definitions/api.BarMap" } } @@ -67,7 +65,6 @@ "200": { "description": "OK", "schema": { - "type": "object", "$ref": "#/definitions/api.Foo" } } @@ -88,7 +85,6 @@ "200": { "description": "OK", "schema": { - "type": "object", "$ref": "#/definitions/api.FooBar" } } @@ -109,7 +105,6 @@ "200": { "description": "OK", "schema": { - "type": "object", "$ref": "#/definitions/api.FooBarPointer" } } diff --git a/testdata/simple2/docs/docs.go b/testdata/simple2/docs/docs.go index 7c77fcc06..c26d9c592 100644 --- a/testdata/simple2/docs/docs.go +++ b/testdata/simple2/docs/docs.go @@ -1,6 +1,6 @@ // GENERATED BY THE COMMAND ABOVE; DO NOT EDIT // This file was generated by swaggo/swag at -// 2019-07-15 21:17:57.384551624 +0900 JST m=+0.027691337 +// 2019-07-17 15:20:42.924557146 +0300 EEST m=+0.051318783 package docs @@ -63,14 +63,12 @@ var doc = `{ "400": { "description": "We need ID!!", "schema": { - "type": "object", "$ref": "#/definitions/web.APIError" } }, "404": { "description": "Can not find ID", "schema": { - "type": "object", "$ref": "#/definitions/web.APIError" } } @@ -118,14 +116,12 @@ var doc = `{ "400": { "description": "We need ID!!", "schema": { - "type": "object", "$ref": "#/definitions/web.APIError" } }, "404": { "description": "Can not find ID", "schema": { - "type": "object", "$ref": "#/definitions/web.APIError" } } @@ -230,14 +226,12 @@ var doc = `{ "400": { "description": "We need ID!!", "schema": { - "type": "object", "$ref": "#/definitions/web.APIError" } }, "404": { "description": "Can not find ID", "schema": { - "type": "object", "$ref": "#/definitions/web.APIError" } } @@ -502,13 +496,13 @@ type swaggerInfo struct { } // SwaggerInfo holds exported Swagger Info so clients can modify it -var SwaggerInfo = swaggerInfo{Schemes: []string{}} +var SwaggerInfo = swaggerInfo{ Schemes: []string{}} type s struct{} func (s *s) ReadDoc() string { t, err := template.New("swagger_info").Funcs(template.FuncMap{ - "marshal": func(v interface{}) string { + "marshal": func(v interface {}) string { a, _ := json.Marshal(v) return string(a) }, diff --git a/testdata/simple3/docs/docs.go b/testdata/simple3/docs/docs.go index fc36c3d83..14ff2a447 100644 --- a/testdata/simple3/docs/docs.go +++ b/testdata/simple3/docs/docs.go @@ -1,6 +1,6 @@ // GENERATED BY THE COMMAND ABOVE; DO NOT EDIT // This file was generated by swaggo/swag at -// 2019-07-15 21:17:57.389489669 +0900 JST m=+0.032629371 +// 2019-07-17 15:20:42.93325927 +0300 EEST m=+0.060021004 package docs @@ -63,14 +63,12 @@ var doc = `{ "400": { "description": "We need ID!!", "schema": { - "type": "object", "$ref": "#/definitions/web.APIError" } }, "404": { "description": "Can not find ID", "schema": { - "type": "object", "$ref": "#/definitions/web.APIError" } } @@ -118,14 +116,12 @@ var doc = `{ "400": { "description": "We need ID!!", "schema": { - "type": "object", "$ref": "#/definitions/web.APIError" } }, "404": { "description": "Can not find ID", "schema": { - "type": "object", "$ref": "#/definitions/web.APIError" } } @@ -230,14 +226,12 @@ var doc = `{ "400": { "description": "We need ID!!", "schema": { - "type": "object", "$ref": "#/definitions/web.APIError" } }, "404": { "description": "Can not find ID", "schema": { - "type": "object", "$ref": "#/definitions/web.APIError" } } @@ -475,13 +469,13 @@ type swaggerInfo struct { } // SwaggerInfo holds exported Swagger Info so clients can modify it -var SwaggerInfo = swaggerInfo{Schemes: []string{}} +var SwaggerInfo = swaggerInfo{ Schemes: []string{}} type s struct{} func (s *s) ReadDoc() string { t, err := template.New("swagger_info").Funcs(template.FuncMap{ - "marshal": func(v interface{}) string { + "marshal": func(v interface {}) string { a, _ := json.Marshal(v) return string(a) }, From 50cd5d1ebd0b27005467ac7464f10713da27446b Mon Sep 17 00:00:00 2001 From: Bogdan Ungureanu Date: Wed, 17 Jul 2019 15:36:52 +0300 Subject: [PATCH 2/5] Pass Travis CI tests --- example/basic/docs/docs.go | 6 +- example/basic/docs/swagger/swagger.json | 249 ------ example/celler/docs/docs.go | 72 +- example/celler/docs/swagger/swagger.json | 1026 ---------------------- example/celler/docs/swagger/swagger.yaml | 35 - gen/gen.go | 4 +- 6 files changed, 40 insertions(+), 1352 deletions(-) delete mode 100644 example/basic/docs/swagger/swagger.json delete mode 100644 example/celler/docs/swagger/swagger.json diff --git a/example/basic/docs/docs.go b/example/basic/docs/docs.go index d6e005b55..5d436867e 100644 --- a/example/basic/docs/docs.go +++ b/example/basic/docs/docs.go @@ -1,6 +1,6 @@ // GENERATED BY THE COMMAND ABOVE; DO NOT EDIT // This file was generated by swaggo/swag at -// 2019-07-17 15:09:52.573759118 +0300 EEST m=+0.033526900 +// 2019-07-17 15:34:26.038643394 +0300 EEST m=+0.024553500 package docs @@ -273,13 +273,13 @@ type swaggerInfo struct { } // SwaggerInfo holds exported Swagger Info so clients can modify it -var SwaggerInfo = swaggerInfo{ Schemes: []string{}} +var SwaggerInfo = swaggerInfo{Schemes: []string{}} type s struct{} func (s *s) ReadDoc() string { t, err := template.New("swagger_info").Funcs(template.FuncMap{ - "marshal": func(v interface {}) string { + "marshal": func(v interface{}) string { a, _ := json.Marshal(v) return string(a) }, diff --git a/example/basic/docs/swagger/swagger.json b/example/basic/docs/swagger/swagger.json deleted file mode 100644 index a482a190a..000000000 --- a/example/basic/docs/swagger/swagger.json +++ /dev/null @@ -1,249 +0,0 @@ -{ - "swagger": "2.0", - "info": { - "description": "This is a sample server Petstore server.", - "title": "Swagger Example API", - "termsOfService": "http://swagger.io/terms/", - "contact": { - "name": "API Support", - "url": "http://www.swagger.io/support", - "email": "support@swagger.io" - }, - "license": { - "name": "Apache 2.0", - "url": "http://www.apache.org/licenses/LICENSE-2.0.html" - }, - "version": "1.0" - }, - "host": "petstore.swagger.io", - "basePath": "/v2", - "paths": { - "/file/upload": { - "post": { - "description": "Upload file", - "consumes": [ - "multipart/form-data" - ], - "produces": [ - "application/json" - ], - "summary": "Upload file", - "operationId": "file.upload", - "parameters": [ - { - "type": "file", - "description": "this is a test file", - "name": "file", - "in": "formData", - "required": true - } - ], - "responses": { - "200": { - "description": "ok", - "schema": { - "type": "string" - } - }, - "400": { - "description": "We need ID!!", - "schema": { - "$ref": "#/definitions/web.APIError" - } - }, - "404": { - "description": "Can not find ID", - "schema": { - "$ref": "#/definitions/web.APIError" - } - } - } - } - }, - "/testapi/get-string-by-int/{some_id}": { - "get": { - "description": "get string by ID", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "summary": "Add a new pet to the store", - "operationId": "get-string-by-int", - "parameters": [ - { - "type": "integer", - "description": "Some ID", - "name": "some_id", - "in": "path", - "required": true - }, - { - "description": "Some ID", - "name": "some_id", - "in": "body", - "required": true, - "schema": { - "type": "object", - "$ref": "#/definitions/web.Pet" - } - } - ], - "responses": { - "200": { - "description": "ok", - "schema": { - "type": "string" - } - }, - "400": { - "description": "We need ID!!", - "schema": { - "$ref": "#/definitions/web.APIError" - } - }, - "404": { - "description": "Can not find ID", - "schema": { - "$ref": "#/definitions/web.APIError" - } - } - } - } - }, - "/testapi/get-struct-array-by-string/{some_id}": { - "get": { - "description": "get struct array by ID", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "operationId": "get-struct-array-by-string", - "parameters": [ - { - "type": "string", - "description": "Some ID", - "name": "some_id", - "in": "path", - "required": true - }, - { - "type": "integer", - "description": "Offset", - "name": "offset", - "in": "query", - "required": true - }, - { - "type": "integer", - "description": "Offset", - "name": "limit", - "in": "query", - "required": true - } - ], - "responses": { - "200": { - "description": "ok", - "schema": { - "type": "string" - } - }, - "400": { - "description": "We need ID!!", - "schema": { - "$ref": "#/definitions/web.APIError" - } - }, - "404": { - "description": "Can not find ID", - "schema": { - "$ref": "#/definitions/web.APIError" - } - } - } - } - } - }, - "definitions": { - "web.APIError": { - "type": "object", - "properties": { - "createdAt": { - "type": "string" - }, - "errorCode": { - "type": "integer" - }, - "errorMessage": { - "type": "string" - } - } - }, - "web.Pet": { - "type": "object", - "properties": { - "category": { - "type": "object", - "properties": { - "id": { - "type": "integer" - }, - "name": { - "type": "string" - } - } - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string" - }, - "photoUrls": { - "type": "array", - "items": { - "type": "string" - } - }, - "status": { - "type": "string" - }, - "tags": { - "type": "array", - "items": { - "$ref": "#/definitions/web.Tag" - } - } - } - }, - "web.RevValue": { - "type": "object", - "properties": { - "Data": { - "type": "integer" - }, - "Err": { - "type": "integer" - }, - "Status": { - "type": "boolean" - } - } - }, - "web.Tag": { - "type": "object", - "properties": { - "id": { - "type": "integer" - }, - "name": { - "type": "string" - } - } - } - } -} \ No newline at end of file diff --git a/example/celler/docs/docs.go b/example/celler/docs/docs.go index e978e30da..57feb4ab0 100644 --- a/example/celler/docs/docs.go +++ b/example/celler/docs/docs.go @@ -1,14 +1,19 @@ // GENERATED BY THE COMMAND ABOVE; DO NOT EDIT // This file was generated by swaggo/swag at -// 2018-05-05 22:29:48.833115021 +0900 JST m=+0.036334289 +// 2019-07-17 15:35:16.190502399 +0300 EEST m=+0.036572790 package docs import ( + "bytes" + "encoding/json" + + "github.com/alecthomas/template" "github.com/swaggo/swag" ) var doc = `{ + "schemes": {{ marshal .Schemes }}, "swagger": "2.0", "info": { "description": "This is a sample server celler server.", @@ -63,21 +68,18 @@ var doc = `{ "400": { "description": "Bad Request", "schema": { - "type": "object", "$ref": "#/definitions/httputil.HTTPError" } }, "404": { "description": "Not Found", "schema": { - "type": "object", "$ref": "#/definitions/httputil.HTTPError" } }, "500": { "description": "Internal Server Error", "schema": { - "type": "object", "$ref": "#/definitions/httputil.HTTPError" } } @@ -111,28 +113,24 @@ var doc = `{ "200": { "description": "OK", "schema": { - "type": "object", "$ref": "#/definitions/model.Account" } }, "400": { "description": "Bad Request", "schema": { - "type": "object", "$ref": "#/definitions/httputil.HTTPError" } }, "404": { "description": "Not Found", "schema": { - "type": "object", "$ref": "#/definitions/httputil.HTTPError" } }, "500": { "description": "Internal Server Error", "schema": { - "type": "object", "$ref": "#/definitions/httputil.HTTPError" } } @@ -165,28 +163,24 @@ var doc = `{ "200": { "description": "OK", "schema": { - "type": "object", "$ref": "#/definitions/model.Account" } }, "400": { "description": "Bad Request", "schema": { - "type": "object", "$ref": "#/definitions/httputil.HTTPError" } }, "404": { "description": "Not Found", "schema": { - "type": "object", "$ref": "#/definitions/httputil.HTTPError" } }, "500": { "description": "Internal Server Error", "schema": { - "type": "object", "$ref": "#/definitions/httputil.HTTPError" } } @@ -218,28 +212,24 @@ var doc = `{ "204": { "description": "No Content", "schema": { - "type": "object", "$ref": "#/definitions/model.Account" } }, "400": { "description": "Bad Request", "schema": { - "type": "object", "$ref": "#/definitions/httputil.HTTPError" } }, "404": { "description": "Not Found", "schema": { - "type": "object", "$ref": "#/definitions/httputil.HTTPError" } }, "500": { "description": "Internal Server Error", "schema": { - "type": "object", "$ref": "#/definitions/httputil.HTTPError" } } @@ -280,28 +270,24 @@ var doc = `{ "200": { "description": "OK", "schema": { - "type": "object", "$ref": "#/definitions/model.Account" } }, "400": { "description": "Bad Request", "schema": { - "type": "object", "$ref": "#/definitions/httputil.HTTPError" } }, "404": { "description": "Not Found", "schema": { - "type": "object", "$ref": "#/definitions/httputil.HTTPError" } }, "500": { "description": "Internal Server Error", "schema": { - "type": "object", "$ref": "#/definitions/httputil.HTTPError" } } @@ -341,28 +327,24 @@ var doc = `{ "200": { "description": "OK", "schema": { - "type": "object", "$ref": "#/definitions/controller.Message" } }, "400": { "description": "Bad Request", "schema": { - "type": "object", "$ref": "#/definitions/httputil.HTTPError" } }, "404": { "description": "Not Found", "schema": { - "type": "object", "$ref": "#/definitions/httputil.HTTPError" } }, "500": { "description": "Internal Server Error", "schema": { - "type": "object", "$ref": "#/definitions/httputil.HTTPError" } } @@ -392,35 +374,30 @@ var doc = `{ "200": { "description": "OK", "schema": { - "type": "object", "$ref": "#/definitions/model.Admin" } }, "400": { "description": "Bad Request", "schema": { - "type": "object", "$ref": "#/definitions/httputil.HTTPError" } }, "401": { "description": "Unauthorized", "schema": { - "type": "object", "$ref": "#/definitions/httputil.HTTPError" } }, "404": { "description": "Not Found", "schema": { - "type": "object", "$ref": "#/definitions/httputil.HTTPError" } }, "500": { "description": "Internal Server Error", "schema": { - "type": "object", "$ref": "#/definitions/httputil.HTTPError" } } @@ -453,21 +430,18 @@ var doc = `{ "400": { "description": "Bad Request", "schema": { - "type": "object", "$ref": "#/definitions/httputil.HTTPError" } }, "404": { "description": "Not Found", "schema": { - "type": "object", "$ref": "#/definitions/httputil.HTTPError" } }, "500": { "description": "Internal Server Error", "schema": { - "type": "object", "$ref": "#/definitions/httputil.HTTPError" } } @@ -501,28 +475,24 @@ var doc = `{ "200": { "description": "OK", "schema": { - "type": "object", "$ref": "#/definitions/model.Bottle" } }, "400": { "description": "Bad Request", "schema": { - "type": "object", "$ref": "#/definitions/httputil.HTTPError" } }, "404": { "description": "Not Found", "schema": { - "type": "object", "$ref": "#/definitions/httputil.HTTPError" } }, "500": { "description": "Internal Server Error", "schema": { - "type": "object", "$ref": "#/definitions/httputil.HTTPError" } } @@ -1035,11 +1005,39 @@ var doc = `{ } }` +type swaggerInfo struct { + Version string + Host string + BasePath string + Schemes []string + Title string + Description string +} + +// SwaggerInfo holds exported Swagger Info so clients can modify it +var SwaggerInfo = swaggerInfo{Schemes: []string{}} + type s struct{} func (s *s) ReadDoc() string { - return doc + t, err := template.New("swagger_info").Funcs(template.FuncMap{ + "marshal": func(v interface{}) string { + a, _ := json.Marshal(v) + return string(a) + }, + }).Parse(doc) + if err != nil { + return doc + } + + var tpl bytes.Buffer + if err := t.Execute(&tpl, SwaggerInfo); err != nil { + return doc + } + + return tpl.String() } + func init() { swag.Register(swag.Name, &s{}) } diff --git a/example/celler/docs/swagger/swagger.json b/example/celler/docs/swagger/swagger.json deleted file mode 100644 index c1b75c310..000000000 --- a/example/celler/docs/swagger/swagger.json +++ /dev/null @@ -1,1026 +0,0 @@ -{ - "swagger": "2.0", - "info": { - "description": "This is a sample server celler server.", - "title": "Swagger Example API", - "termsOfService": "http://swagger.io/terms/", - "contact": { - "name": "API Support", - "url": "http://www.swagger.io/support", - "email": "support@swagger.io" - }, - "license": { - "name": "Apache 2.0", - "url": "http://www.apache.org/licenses/LICENSE-2.0.html" - }, - "version": "1.0" - }, - "host": "localhost:8080", - "basePath": "/api/v1", - "paths": { - "/accounts": { - "get": { - "description": "get accounts", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "accounts" - ], - "summary": "List accounts", - "parameters": [ - { - "type": "string", - "format": "email", - "description": "name search by q", - "name": "q", - "in": "query" - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.Account" - } - } - }, - "400": { - "description": "Bad Request", - "schema": { - "type": "object", - "$ref": "#/definitions/httputil.HTTPError" - } - }, - "404": { - "description": "Not Found", - "schema": { - "type": "object", - "$ref": "#/definitions/httputil.HTTPError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "type": "object", - "$ref": "#/definitions/httputil.HTTPError" - } - } - } - }, - "post": { - "description": "add by json account", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "accounts" - ], - "summary": "Add a account", - "parameters": [ - { - "description": "Add account", - "name": "account", - "in": "body", - "required": true, - "schema": { - "type": "object", - "$ref": "#/definitions/model.AddAccount" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "object", - "$ref": "#/definitions/model.Account" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "type": "object", - "$ref": "#/definitions/httputil.HTTPError" - } - }, - "404": { - "description": "Not Found", - "schema": { - "type": "object", - "$ref": "#/definitions/httputil.HTTPError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "type": "object", - "$ref": "#/definitions/httputil.HTTPError" - } - } - } - } - }, - "/accounts/{id}": { - "get": { - "description": "get string by ID", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "accounts" - ], - "summary": "Show a account", - "parameters": [ - { - "type": "integer", - "description": "Account ID", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "object", - "$ref": "#/definitions/model.Account" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "type": "object", - "$ref": "#/definitions/httputil.HTTPError" - } - }, - "404": { - "description": "Not Found", - "schema": { - "type": "object", - "$ref": "#/definitions/httputil.HTTPError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "type": "object", - "$ref": "#/definitions/httputil.HTTPError" - } - } - } - }, - "delete": { - "description": "Delete by account ID", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "accounts" - ], - "summary": "Update a account", - "parameters": [ - { - "type": "integer", - "format": "int64", - "description": "Account ID", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "204": { - "description": "No Content", - "schema": { - "type": "object", - "$ref": "#/definitions/model.Account" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "type": "object", - "$ref": "#/definitions/httputil.HTTPError" - } - }, - "404": { - "description": "Not Found", - "schema": { - "type": "object", - "$ref": "#/definitions/httputil.HTTPError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "type": "object", - "$ref": "#/definitions/httputil.HTTPError" - } - } - } - }, - "patch": { - "description": "Update by json account", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "accounts" - ], - "summary": "Update a account", - "parameters": [ - { - "type": "integer", - "description": "Account ID", - "name": "id", - "in": "path", - "required": true - }, - { - "description": "Update account", - "name": "account", - "in": "body", - "required": true, - "schema": { - "type": "object", - "$ref": "#/definitions/model.UpdateAccount" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "object", - "$ref": "#/definitions/model.Account" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "type": "object", - "$ref": "#/definitions/httputil.HTTPError" - } - }, - "404": { - "description": "Not Found", - "schema": { - "type": "object", - "$ref": "#/definitions/httputil.HTTPError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "type": "object", - "$ref": "#/definitions/httputil.HTTPError" - } - } - } - } - }, - "/accounts/{id}/images": { - "post": { - "description": "Upload file", - "consumes": [ - "multipart/form-data" - ], - "produces": [ - "application/json" - ], - "tags": [ - "accounts" - ], - "summary": "Upload account image", - "parameters": [ - { - "type": "integer", - "description": "Account ID", - "name": "id", - "in": "path", - "required": true - }, - { - "type": "file", - "description": "account image", - "name": "file", - "in": "formData", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "object", - "$ref": "#/definitions/controller.Message" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "type": "object", - "$ref": "#/definitions/httputil.HTTPError" - } - }, - "404": { - "description": "Not Found", - "schema": { - "type": "object", - "$ref": "#/definitions/httputil.HTTPError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "type": "object", - "$ref": "#/definitions/httputil.HTTPError" - } - } - } - } - }, - "/admin/auth": { - "post": { - "security": [ - { - "ApiKeyAuth": [] - } - ], - "description": "get admin info", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "accounts", - "admin" - ], - "summary": "Auth admin", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "object", - "$ref": "#/definitions/model.Admin" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "type": "object", - "$ref": "#/definitions/httputil.HTTPError" - } - }, - "401": { - "description": "Unauthorized", - "schema": { - "type": "object", - "$ref": "#/definitions/httputil.HTTPError" - } - }, - "404": { - "description": "Not Found", - "schema": { - "type": "object", - "$ref": "#/definitions/httputil.HTTPError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "type": "object", - "$ref": "#/definitions/httputil.HTTPError" - } - } - } - } - }, - "/bottles": { - "get": { - "description": "get bottles", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "bottles" - ], - "summary": "List bottles", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/model.Bottle" - } - } - }, - "400": { - "description": "Bad Request", - "schema": { - "type": "object", - "$ref": "#/definitions/httputil.HTTPError" - } - }, - "404": { - "description": "Not Found", - "schema": { - "type": "object", - "$ref": "#/definitions/httputil.HTTPError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "type": "object", - "$ref": "#/definitions/httputil.HTTPError" - } - } - } - } - }, - "/bottles/{id}": { - "get": { - "description": "get string by ID", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "bottles" - ], - "summary": "Show a bottle", - "operationId": "get-string-by-int", - "parameters": [ - { - "type": "integer", - "description": "Bottle ID", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "object", - "$ref": "#/definitions/model.Bottle" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "type": "object", - "$ref": "#/definitions/httputil.HTTPError" - } - }, - "404": { - "description": "Not Found", - "schema": { - "type": "object", - "$ref": "#/definitions/httputil.HTTPError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "type": "object", - "$ref": "#/definitions/httputil.HTTPError" - } - } - } - } - }, - "/examples/attribute": { - "get": { - "description": "attribute", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "example" - ], - "summary": "attribute example", - "parameters": [ - { - "enum": [ - "A", - "B", - "C" - ], - "type": "string", - "description": "string enums", - "name": "enumstring", - "in": "query" - }, - { - "enum": [ - 1, - 2, - 3 - ], - "type": "integer", - "description": "int enums", - "name": "enumint", - "in": "query" - }, - { - "enum": [ - 1.1, - 1.2, - 1.3 - ], - "type": "number", - "description": "int enums", - "name": "enumnumber", - "in": "query" - }, - { - "maxLength": 10, - "minLength": 5, - "type": "string", - "description": "string valid", - "name": "string", - "in": "query" - }, - { - "maximum": 10, - "minimum": 1, - "type": "integer", - "description": "int valid", - "name": "int", - "in": "query" - }, - { - "type": "string", - "default": "A", - "description": "string default", - "name": "default", - "in": "query" - } - ], - "responses": { - "200": { - "description": "answer", - "schema": { - "type": "string" - } - }, - "400": { - "description": "ok", - "schema": { - "type": "string" - } - }, - "404": { - "description": "ok", - "schema": { - "type": "string" - } - }, - "500": { - "description": "ok", - "schema": { - "type": "string" - } - } - } - } - }, - "/examples/calc": { - "get": { - "description": "plus", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "example" - ], - "summary": "calc example", - "parameters": [ - { - "type": "integer", - "description": "used for calc", - "name": "val1", - "in": "query", - "required": true - }, - { - "type": "integer", - "description": "used for calc", - "name": "val2", - "in": "query", - "required": true - } - ], - "responses": { - "200": { - "description": "answer", - "schema": { - "type": "integer" - } - }, - "400": { - "description": "ok", - "schema": { - "type": "string" - } - }, - "404": { - "description": "ok", - "schema": { - "type": "string" - } - }, - "500": { - "description": "ok", - "schema": { - "type": "string" - } - } - } - } - }, - "/examples/groups/{group_id}/accounts/{account_id}": { - "get": { - "description": "path params", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "example" - ], - "summary": "path params example", - "parameters": [ - { - "type": "integer", - "description": "Group ID", - "name": "group_id", - "in": "path", - "required": true - }, - { - "type": "integer", - "description": "Account ID", - "name": "account_id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "answer", - "schema": { - "type": "string" - } - }, - "400": { - "description": "ok", - "schema": { - "type": "string" - } - }, - "404": { - "description": "ok", - "schema": { - "type": "string" - } - }, - "500": { - "description": "ok", - "schema": { - "type": "string" - } - } - } - } - }, - "/examples/header": { - "get": { - "description": "custome header", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "example" - ], - "summary": "custome header example", - "parameters": [ - { - "type": "string", - "description": "Authentication header", - "name": "Authorization", - "in": "header", - "required": true - } - ], - "responses": { - "200": { - "description": "answer", - "schema": { - "type": "string" - } - }, - "400": { - "description": "ok", - "schema": { - "type": "string" - } - }, - "404": { - "description": "ok", - "schema": { - "type": "string" - } - }, - "500": { - "description": "ok", - "schema": { - "type": "string" - } - } - } - } - }, - "/examples/ping": { - "get": { - "description": "do ping", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "example" - ], - "summary": "ping example", - "responses": { - "200": { - "description": "pong", - "schema": { - "type": "string" - } - }, - "400": { - "description": "ok", - "schema": { - "type": "string" - } - }, - "404": { - "description": "ok", - "schema": { - "type": "string" - } - }, - "500": { - "description": "ok", - "schema": { - "type": "string" - } - } - } - } - }, - "/examples/securities": { - "get": { - "security": [ - { - "ApiKeyAuth": [] - }, - { - "OAuth2Implicit": [ - "admin", - "write" - ] - } - ], - "description": "custome header", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "example" - ], - "summary": "custome header example", - "parameters": [ - { - "type": "string", - "description": "Authentication header", - "name": "Authorization", - "in": "header", - "required": true - } - ], - "responses": { - "200": { - "description": "answer", - "schema": { - "type": "string" - } - }, - "400": { - "description": "ok", - "schema": { - "type": "string" - } - }, - "404": { - "description": "ok", - "schema": { - "type": "string" - } - }, - "500": { - "description": "ok", - "schema": { - "type": "string" - } - } - } - } - } - }, - "definitions": { - "controller.Message": { - "type": "object", - "properties": { - "message": { - "type": "string", - "example": "message" - } - } - }, - "httputil.HTTPError": { - "type": "object", - "properties": { - "code": { - "type": "integer", - "example": 400 - }, - "message": { - "type": "string", - "example": "status bad request" - } - } - }, - "model.Account": { - "type": "object", - "properties": { - "id": { - "type": "integer", - "format": "int64", - "example": 1 - }, - "name": { - "type": "string", - "example": "account name" - }, - "uuid": { - "type": "string", - "format": "uuid", - "example": "550e8400-e29b-41d4-a716-446655440000" - } - } - }, - "model.AddAccount": { - "type": "object", - "properties": { - "name": { - "type": "string", - "example": "account name" - } - } - }, - "model.Admin": { - "type": "object", - "properties": { - "id": { - "type": "integer", - "example": 1 - }, - "name": { - "type": "string", - "example": "admin name" - } - } - }, - "model.Bottle": { - "type": "object", - "properties": { - "account": { - "type": "object", - "$ref": "#/definitions/model.Account" - }, - "id": { - "type": "integer", - "example": 1 - }, - "name": { - "type": "string", - "example": "bottle_name" - } - } - }, - "model.UpdateAccount": { - "type": "object", - "properties": { - "name": { - "type": "string", - "example": "account name" - } - } - } - }, - "securityDefinitions": { - "ApiKeyAuth": { - "type": "apiKey", - "name": "Authorization", - "in": "header" - }, - "BasicAuth": { - "type": "basic" - }, - "OAuth2AccessCode": { - "type": "oauth2", - "flow": "accessCode", - "authorizationUrl": "https://example.com/oauth/authorize", - "tokenUrl": "https://example.com/oauth/token", - "scopes": { - "admin": " Grants read and write access to administrative information" - } - }, - "OAuth2Application": { - "type": "oauth2", - "flow": "application", - "tokenUrl": "https://example.com/oauth/token", - "scopes": { - "admin": " Grants read and write access to administrative information", - "write": " Grants write access" - } - }, - "OAuth2Implicit": { - "type": "oauth2", - "flow": "implicit", - "authorizationUrl": "https://example.com/oauth/authorize", - "scopes": { - "admin": " Grants read and write access to administrative information", - "write": " Grants write access" - } - }, - "OAuth2Password": { - "type": "oauth2", - "flow": "password", - "tokenUrl": "https://example.com/oauth/token", - "scopes": { - "admin": " Grants read and write access to administrative information", - "read": " Grants read access", - "write": " Grants write access" - } - } - } -} \ No newline at end of file diff --git a/example/celler/docs/swagger/swagger.yaml b/example/celler/docs/swagger/swagger.yaml index b5f8fa933..000953a72 100644 --- a/example/celler/docs/swagger/swagger.yaml +++ b/example/celler/docs/swagger/swagger.yaml @@ -100,17 +100,14 @@ paths: description: Bad Request schema: $ref: '#/definitions/httputil.HTTPError' - type: object "404": description: Not Found schema: $ref: '#/definitions/httputil.HTTPError' - type: object "500": description: Internal Server Error schema: $ref: '#/definitions/httputil.HTTPError' - type: object summary: List accounts tags: - accounts @@ -133,22 +130,18 @@ paths: description: OK schema: $ref: '#/definitions/model.Account' - type: object "400": description: Bad Request schema: $ref: '#/definitions/httputil.HTTPError' - type: object "404": description: Not Found schema: $ref: '#/definitions/httputil.HTTPError' - type: object "500": description: Internal Server Error schema: $ref: '#/definitions/httputil.HTTPError' - type: object summary: Add a account tags: - accounts @@ -171,22 +164,18 @@ paths: description: No Content schema: $ref: '#/definitions/model.Account' - type: object "400": description: Bad Request schema: $ref: '#/definitions/httputil.HTTPError' - type: object "404": description: Not Found schema: $ref: '#/definitions/httputil.HTTPError' - type: object "500": description: Internal Server Error schema: $ref: '#/definitions/httputil.HTTPError' - type: object summary: Update a account tags: - accounts @@ -207,22 +196,18 @@ paths: description: OK schema: $ref: '#/definitions/model.Account' - type: object "400": description: Bad Request schema: $ref: '#/definitions/httputil.HTTPError' - type: object "404": description: Not Found schema: $ref: '#/definitions/httputil.HTTPError' - type: object "500": description: Internal Server Error schema: $ref: '#/definitions/httputil.HTTPError' - type: object summary: Show a account tags: - accounts @@ -250,22 +235,18 @@ paths: description: OK schema: $ref: '#/definitions/model.Account' - type: object "400": description: Bad Request schema: $ref: '#/definitions/httputil.HTTPError' - type: object "404": description: Not Found schema: $ref: '#/definitions/httputil.HTTPError' - type: object "500": description: Internal Server Error schema: $ref: '#/definitions/httputil.HTTPError' - type: object summary: Update a account tags: - accounts @@ -292,22 +273,18 @@ paths: description: OK schema: $ref: '#/definitions/controller.Message' - type: object "400": description: Bad Request schema: $ref: '#/definitions/httputil.HTTPError' - type: object "404": description: Not Found schema: $ref: '#/definitions/httputil.HTTPError' - type: object "500": description: Internal Server Error schema: $ref: '#/definitions/httputil.HTTPError' - type: object summary: Upload account image tags: - accounts @@ -323,27 +300,22 @@ paths: description: OK schema: $ref: '#/definitions/model.Admin' - type: object "400": description: Bad Request schema: $ref: '#/definitions/httputil.HTTPError' - type: object "401": description: Unauthorized schema: $ref: '#/definitions/httputil.HTTPError' - type: object "404": description: Not Found schema: $ref: '#/definitions/httputil.HTTPError' - type: object "500": description: Internal Server Error schema: $ref: '#/definitions/httputil.HTTPError' - type: object security: - ApiKeyAuth: [] summary: Auth admin @@ -368,17 +340,14 @@ paths: description: Bad Request schema: $ref: '#/definitions/httputil.HTTPError' - type: object "404": description: Not Found schema: $ref: '#/definitions/httputil.HTTPError' - type: object "500": description: Internal Server Error schema: $ref: '#/definitions/httputil.HTTPError' - type: object summary: List bottles tags: - bottles @@ -401,22 +370,18 @@ paths: description: OK schema: $ref: '#/definitions/model.Bottle' - type: object "400": description: Bad Request schema: $ref: '#/definitions/httputil.HTTPError' - type: object "404": description: Not Found schema: $ref: '#/definitions/httputil.HTTPError' - type: object "500": description: Internal Server Error schema: $ref: '#/definitions/httputil.HTTPError' - type: object summary: Show a bottle tags: - bottles diff --git a/gen/gen.go b/gen/gen.go index 10d86f0fe..b6127d44e 100644 --- a/gen/gen.go +++ b/gen/gen.go @@ -161,13 +161,13 @@ type swaggerInfo struct { } // SwaggerInfo holds exported Swagger Info so clients can modify it -var SwaggerInfo = swaggerInfo{ Schemes: {{.Schemes}}} +var SwaggerInfo = swaggerInfo{Schemes: {{.Schemes}}} type s struct{} func (s *s) ReadDoc() string { t, err := template.New("swagger_info").Funcs(template.FuncMap{ - "marshal": func(v interface {}) string { + "marshal": func(v interface{}) string { a, _ := json.Marshal(v) return string(a) }, From 37963073ab7d1fae8eabd5c40f03b3b8250e2fd5 Mon Sep 17 00:00:00 2001 From: Bogdan Ungureanu Date: Wed, 17 Jul 2019 15:49:38 +0300 Subject: [PATCH 3/5] Pass Travis CI tests --- testdata/simple2/docs/docs.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/testdata/simple2/docs/docs.go b/testdata/simple2/docs/docs.go index c26d9c592..0d5fb68b1 100644 --- a/testdata/simple2/docs/docs.go +++ b/testdata/simple2/docs/docs.go @@ -1,6 +1,6 @@ // GENERATED BY THE COMMAND ABOVE; DO NOT EDIT // This file was generated by swaggo/swag at -// 2019-07-17 15:20:42.924557146 +0300 EEST m=+0.051318783 +// 2019-07-17 15:34:45.975640886 +0300 EEST m=+0.051468436 package docs @@ -496,13 +496,13 @@ type swaggerInfo struct { } // SwaggerInfo holds exported Swagger Info so clients can modify it -var SwaggerInfo = swaggerInfo{ Schemes: []string{}} +var SwaggerInfo = swaggerInfo{Schemes: []string{}} type s struct{} func (s *s) ReadDoc() string { t, err := template.New("swagger_info").Funcs(template.FuncMap{ - "marshal": func(v interface {}) string { + "marshal": func(v interface{}) string { a, _ := json.Marshal(v) return string(a) }, From be816bbb4f31212ed7212088ae618a21ad6b1360 Mon Sep 17 00:00:00 2001 From: Bogdan Ungureanu Date: Wed, 17 Jul 2019 15:54:35 +0300 Subject: [PATCH 4/5] Pass Travis CI tests - again --- testdata/simple3/docs/docs.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/testdata/simple3/docs/docs.go b/testdata/simple3/docs/docs.go index 14ff2a447..f76bad30a 100644 --- a/testdata/simple3/docs/docs.go +++ b/testdata/simple3/docs/docs.go @@ -1,6 +1,6 @@ // GENERATED BY THE COMMAND ABOVE; DO NOT EDIT // This file was generated by swaggo/swag at -// 2019-07-17 15:20:42.93325927 +0300 EEST m=+0.060021004 +// 2019-07-17 15:54:04.765591008 +0300 EEST m=+0.039056976 package docs @@ -469,13 +469,13 @@ type swaggerInfo struct { } // SwaggerInfo holds exported Swagger Info so clients can modify it -var SwaggerInfo = swaggerInfo{ Schemes: []string{}} +var SwaggerInfo = swaggerInfo{Schemes: []string{}} type s struct{} func (s *s) ReadDoc() string { t, err := template.New("swagger_info").Funcs(template.FuncMap{ - "marshal": func(v interface {}) string { + "marshal": func(v interface{}) string { a, _ := json.Marshal(v) return string(a) }, From 60a0f32094a8574286d03b9f9478f17adf4cddbe Mon Sep 17 00:00:00 2001 From: Bogdan Ungureanu Date: Thu, 18 Jul 2019 12:42:08 +0300 Subject: [PATCH 5/5] feature: support anonymous nested structure slice parsing --- parser.go | 33 ++++++++++++++++++++++++++- parser_test.go | 59 ++++++++++++++++++++++++++++++++++++++++++++++++ property.go | 4 +++- property_test.go | 17 ++++++++++++++ 4 files changed, 111 insertions(+), 2 deletions(-) diff --git a/parser.go b/parser.go index 74e189f24..86829eeab 100644 --- a/parser.go +++ b/parser.go @@ -886,7 +886,38 @@ func (parser *Parser) parseStruct(pkgName string, field *ast.Field) (map[string] }, }, } - } else { // standard type in array + } else if structField.arrayType == "object" { + // Anonymous struct + if astTypeArray, ok := field.Type.(*ast.ArrayType); ok { // if array + props := make(map[string]spec.Schema) + if expr, ok := astTypeArray.Elt.(*ast.StructType); ok { + for _, field := range expr.Fields.List { + var fieldProps map[string]spec.Schema + fieldProps, err = parser.parseStruct(pkgName, field) + if err != nil { + return properties, err + } + for k, v := range fieldProps { + props[k] = v + } + } + properties[structField.name] = spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{structField.schemaType}, + Description: desc, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: props, + }, + }, + }, + }} + } + } + } else { + // standard type in array required := make([]string, 0) if structField.isRequired { required = append(required, structField.name) diff --git a/parser_test.go b/parser_test.go index 9eae95de7..f3867f119 100644 --- a/parser_test.go +++ b/parser_test.go @@ -2250,6 +2250,65 @@ func TestParseComposition(t *testing.T) { assert.Equal(t, string(expected), string(b)) } +func TestParser_ParseStuctArrayObject(t *testing.T) { + src := ` +package api + +type Response struct { + Code int + Data []struct{ + Field1 uint + Field2 string + } +} + +// @Success 200 {object} Response +// @Router /api/{id} [get] +func Test(){ +} +` + expected := `{ + "api.Response": { + "type": "object", + "properties": { + "code": { + "type": "integer" + }, + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "field1": { + "type": "integer" + }, + "field2": { + "type": "string" + } + } + } + } + } + } +}` + f, err := goparser.ParseFile(token.NewFileSet(), "", src, goparser.ParseComments) + assert.NoError(t, err) + + p := New() + p.ParseType(f) + err = p.ParseRouterAPIInfo("", f) + assert.NoError(t, err) + + typeSpec := p.TypeDefinitions["api"]["Response"] + err = p.ParseDefinition("api", typeSpec.Name.Name, typeSpec) + assert.NoError(t, err) + + out, err := json.MarshalIndent(p.swagger.Definitions, "", " ") + assert.NoError(t, err) + assert.Equal(t, expected, string(out)) + +} + func TestParser_ParseRouterApiInfoErr(t *testing.T) { src := ` package test diff --git a/property.go b/property.go index 11e028213..5b846d63d 100644 --- a/property.go +++ b/property.go @@ -91,6 +91,9 @@ func getPropertyName(expr ast.Expr, parser *Parser) (propertyName, error) { } if astTypeArray, ok := expr.(*ast.ArrayType); ok { // if array + if _, ok := astTypeArray.Elt.(*ast.StructType); ok { + return propertyName{SchemaType: "array", ArrayType: "object"}, nil + } return getArrayPropertyName(astTypeArray, parser), nil } @@ -105,7 +108,6 @@ func getPropertyName(expr ast.Expr, parser *Parser) (propertyName, error) { if _, ok := expr.(*ast.InterfaceType); ok { // if interface{} return propertyName{SchemaType: "object", ArrayType: "object"}, nil } - return propertyName{}, errors.New("not supported" + fmt.Sprint(expr)) } diff --git a/property_test.go b/property_test.go index 6fee73b53..854348cfa 100644 --- a/property_test.go +++ b/property_test.go @@ -225,6 +225,23 @@ func TestGetPropertyNameArrayStarExprSelector(t *testing.T) { assert.Equal(t, expected, propertyName) } +func TestGetPropertyNameArrayStructType(t *testing.T) { + input := &ast.ArrayType{ + Lbrack: 1111, + Len: nil, + Elt: &ast.StructType{}, + } + expected := propertyName{ + "array", + "object", + "", + } + + propertyName, err := getPropertyName(input, New()) + assert.NoError(t, err) + assert.Equal(t, expected, propertyName) +} + func TestGetPropertyNameMap(t *testing.T) { input := &ast.MapType{ Key: &ast.Ident{