diff --git a/examples/clients/abe/ABitOfEverythingNested.go b/examples/clients/abe/ABitOfEverythingNested.go index ab15b89cfbd..7e5488e37a7 100644 --- a/examples/clients/abe/ABitOfEverythingNested.go +++ b/examples/clients/abe/ABitOfEverythingNested.go @@ -4,8 +4,8 @@ import ( ) type ABitOfEverythingNested struct { - Amount int64 `json:"amount,omitempty"` Name string `json:"name,omitempty"` + Amount int64 `json:"amount,omitempty"` Ok NestedDeepEnum `json:"ok,omitempty"` } diff --git a/examples/clients/abe/ExamplepbABitOfEverything.go b/examples/clients/abe/ExamplepbABitOfEverything.go index 2ca345dcc08..3440ace1888 100644 --- a/examples/clients/abe/ExamplepbABitOfEverything.go +++ b/examples/clients/abe/ExamplepbABitOfEverything.go @@ -5,31 +5,31 @@ import ( ) type ExamplepbABitOfEverything struct { - BoolValue bool `json:"bool_value,omitempty"` - DoubleValue float64 `json:"double_value,omitempty"` - EnumValue ExamplepbNumericEnum `json:"enum_value,omitempty"` - Fixed32Value int64 `json:"fixed32_value,omitempty"` - Fixed64Value string `json:"fixed64_value,omitempty"` + SingleNested ABitOfEverythingNested `json:"single_nested,omitempty"` + Uuid string `json:"uuid,omitempty"` + Nested []ABitOfEverythingNested `json:"nested,omitempty"` FloatValue float32 `json:"float_value,omitempty"` - Int32Value int32 `json:"int32_value,omitempty"` + DoubleValue float64 `json:"double_value,omitempty"` Int64Value string `json:"int64_value,omitempty"` - MapValue map[string]ExamplepbNumericEnum `json:"map_value,omitempty"` - MappedNestedValue map[string]ABitOfEverythingNested `json:"mapped_nested_value,omitempty"` - MappedStringValue map[string]string `json:"mapped_string_value,omitempty"` - Nested []ABitOfEverythingNested `json:"nested,omitempty"` - NonConventionalNameValue string `json:"nonConventionalNameValue,omitempty"` - OneofEmpty ProtobufEmpty `json:"oneof_empty,omitempty"` - OneofString string `json:"oneof_string,omitempty"` - RepeatedStringValue []string `json:"repeated_string_value,omitempty"` + Uint64Value string `json:"uint64_value,omitempty"` + Int32Value int32 `json:"int32_value,omitempty"` + Fixed64Value string `json:"fixed64_value,omitempty"` + Fixed32Value int64 `json:"fixed32_value,omitempty"` + BoolValue bool `json:"bool_value,omitempty"` + StringValue string `json:"string_value,omitempty"` + Uint32Value int64 `json:"uint32_value,omitempty"` + EnumValue ExamplepbNumericEnum `json:"enum_value,omitempty"` Sfixed32Value int32 `json:"sfixed32_value,omitempty"` Sfixed64Value string `json:"sfixed64_value,omitempty"` - SingleNested ABitOfEverythingNested `json:"single_nested,omitempty"` Sint32Value int32 `json:"sint32_value,omitempty"` Sint64Value string `json:"sint64_value,omitempty"` - StringValue string `json:"string_value,omitempty"` + RepeatedStringValue []string `json:"repeated_string_value,omitempty"` + OneofEmpty ProtobufEmpty `json:"oneof_empty,omitempty"` + OneofString string `json:"oneof_string,omitempty"` + MapValue map[string]ExamplepbNumericEnum `json:"map_value,omitempty"` + MappedStringValue map[string]string `json:"mapped_string_value,omitempty"` + MappedNestedValue map[string]ABitOfEverythingNested `json:"mapped_nested_value,omitempty"` + NonConventionalNameValue string `json:"nonConventionalNameValue,omitempty"` TimestampValue time.Time `json:"timestamp_value,omitempty"` - Uint32Value int64 `json:"uint32_value,omitempty"` - Uint64Value string `json:"uint64_value,omitempty"` - Uuid string `json:"uuid,omitempty"` } diff --git a/examples/examplepb/a_bit_of_everything.swagger.json b/examples/examplepb/a_bit_of_everything.swagger.json index e8ad64f11d2..0d9366f7ad9 100644 --- a/examples/examplepb/a_bit_of_everything.swagger.json +++ b/examples/examplepb/a_bit_of_everything.swagger.json @@ -363,15 +363,15 @@ "ABitOfEverythingNested": { "type": "object", "properties": { - "amount": { - "type": "integer", - "format": "int64" - }, "name": { "type": "string", "format": "string", "description": "name is nested field." }, + "amount": { + "type": "integer", + "format": "int64" + }, "ok": { "$ref": "#/definitions/NestedDeepEnum" } @@ -390,79 +390,62 @@ "examplepbABitOfEverything": { "type": "object", "properties": { - "bool_value": { - "type": "boolean", - "format": "boolean" + "single_nested": { + "$ref": "#/definitions/ABitOfEverythingNested" + }, + "uuid": { + "type": "string", + "format": "string" + }, + "nested": { + "type": "array", + "items": { + "$ref": "#/definitions/ABitOfEverythingNested" + } + }, + "float_value": { + "type": "number", + "format": "float" }, "double_value": { "type": "number", "format": "double" }, - "enum_value": { - "$ref": "#/definitions/examplepbNumericEnum" - }, - "fixed32_value": { - "type": "integer", + "int64_value": { + "type": "string", "format": "int64" }, - "fixed64_value": { + "uint64_value": { "type": "string", "format": "uint64" }, - "float_value": { - "type": "number", - "format": "float" - }, "int32_value": { "type": "integer", "format": "int32" }, - "int64_value": { + "fixed64_value": { "type": "string", - "format": "int64" - }, - "map_value": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/examplepbNumericEnum" - } - }, - "mapped_nested_value": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/ABitOfEverythingNested" - } + "format": "uint64" }, - "mapped_string_value": { - "type": "object", - "additionalProperties": { - "type": "string", - "format": "string" - } + "fixed32_value": { + "type": "integer", + "format": "int64" }, - "nested": { - "type": "array", - "items": { - "$ref": "#/definitions/ABitOfEverythingNested" - } + "bool_value": { + "type": "boolean", + "format": "boolean" }, - "nonConventionalNameValue": { + "string_value": { "type": "string", "format": "string" }, - "oneof_empty": { - "$ref": "#/definitions/protobufEmpty" - }, - "oneof_string": { - "type": "string", - "format": "string" + "uint32_value": { + "type": "integer", + "format": "int64", + "title": "TODO(yugui) add bytes_value" }, - "repeated_string_value": { - "type": "array", - "items": { - "type": "string", - "format": "string" - } + "enum_value": { + "$ref": "#/definitions/examplepbNumericEnum" }, "sfixed32_value": { "type": "integer", @@ -472,9 +455,6 @@ "type": "string", "format": "int64" }, - "single_nested": { - "$ref": "#/definitions/ABitOfEverythingNested" - }, "sint32_value": { "type": "integer", "format": "int32" @@ -483,26 +463,46 @@ "type": "string", "format": "int64" }, - "string_value": { + "repeated_string_value": { + "type": "array", + "items": { + "type": "string", + "format": "string" + } + }, + "oneof_empty": { + "$ref": "#/definitions/protobufEmpty" + }, + "oneof_string": { "type": "string", "format": "string" }, - "timestamp_value": { - "type": "string", - "format": "date-time" + "map_value": { + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/examplepbNumericEnum" + } }, - "uint32_value": { - "type": "integer", - "format": "int64", - "title": "TODO(yugui) add bytes_value" + "mapped_string_value": { + "type": "object", + "additionalProperties": { + "type": "string", + "format": "string" + } }, - "uint64_value": { - "type": "string", - "format": "uint64" + "mapped_nested_value": { + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/ABitOfEverythingNested" + } }, - "uuid": { + "nonConventionalNameValue": { "type": "string", "format": "string" + }, + "timestamp_value": { + "type": "string", + "format": "date-time" } }, "title": "Intentionaly complicated message type to cover much features of Protobuf.\nNEXT ID: 27" diff --git a/protoc-gen-swagger/genswagger/template.go b/protoc-gen-swagger/genswagger/template.go index b81c4c05635..d2a4cb7b398 100644 --- a/protoc-gen-swagger/genswagger/template.go +++ b/protoc-gen-swagger/genswagger/template.go @@ -62,7 +62,7 @@ func renderMessagesAsDefinition(messages messageMap, d swaggerDefinitionsObject, schemaCore: schemaCore{ Type: "object", }, - Properties: make(map[string]swaggerSchemaObject), + Properties: make(swaggerSchemaObjectProperties, 0), } msgComments := protoComments(reg, msg.File, msg.Outers, "MessageType", int32(msg.Index)) if err := updateSwaggerDataFromComments(&schema, msgComments); err != nil { @@ -78,7 +78,7 @@ func renderMessagesAsDefinition(messages messageMap, d swaggerDefinitionsObject, panic(err) } - schema.Properties[f.GetName()] = fieldValue + schema.Properties = append(schema.Properties, keyVal{f.GetName(), fieldValue}) } d[fullyQualifiedNameToSwaggerName(msg.FQMN(), reg)] = schema } diff --git a/protoc-gen-swagger/genswagger/types.go b/protoc-gen-swagger/genswagger/types.go index b91e457c006..662c7ab3b86 100644 --- a/protoc-gen-swagger/genswagger/types.go +++ b/protoc-gen-swagger/genswagger/types.go @@ -1,6 +1,9 @@ package genswagger import ( + "bytes" + "encoding/json" + "github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway/descriptor" ) @@ -116,13 +119,44 @@ type swaggerResponseObject struct { Schema swaggerSchemaObject `json:"schema"` } +type keyVal struct { + Key string + Value interface{} +} + +type swaggerSchemaObjectProperties []keyVal + +func (op swaggerSchemaObjectProperties) MarshalJSON() ([]byte, error) { + var buf bytes.Buffer + buf.WriteString("{") + for i, kv := range op { + if i != 0 { + buf.WriteString(",") + } + key, err := json.Marshal(kv.Key) + if err != nil { + return nil, err + } + buf.Write(key) + buf.WriteString(":") + val, err := json.Marshal(kv.Value) + if err != nil { + return nil, err + } + buf.Write(val) + } + + buf.WriteString("}") + return buf.Bytes(), nil +} + // http://swagger.io/specification/#schemaObject type swaggerSchemaObject struct { schemaCore // Properties can be recursively defined - Properties map[string]swaggerSchemaObject `json:"properties,omitempty"` - AdditionalProperties *swaggerSchemaObject `json:"additionalProperties,omitempty"` - Items *swaggerItemsObject `json:"items,omitempty"` + Properties swaggerSchemaObjectProperties `json:"properties,omitempty"` + AdditionalProperties *swaggerSchemaObject `json:"additionalProperties,omitempty"` + Items *swaggerItemsObject `json:"items,omitempty"` // If the item is an enumeration include a list of all the *NAMES* of the // enum values. I'm not sure how well this will work but assuming all enums