Skip to content

Commit ad7bba2

Browse files
committed
preserve field order in swagger spec
1 parent 9108558 commit ad7bba2

File tree

5 files changed

+129
-95
lines changed

5 files changed

+129
-95
lines changed

examples/clients/abe/ABitOfEverythingNested.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ import (
44
)
55

66
type ABitOfEverythingNested struct {
7-
Amount int64 `json:"amount,omitempty"`
87
Name string `json:"name,omitempty"`
8+
Amount int64 `json:"amount,omitempty"`
99
Ok NestedDeepEnum `json:"ok,omitempty"`
1010

1111
}

examples/clients/abe/ExamplepbABitOfEverything.go

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,31 +5,31 @@ import (
55
)
66

77
type ExamplepbABitOfEverything struct {
8-
BoolValue bool `json:"bool_value,omitempty"`
9-
DoubleValue float64 `json:"double_value,omitempty"`
10-
EnumValue ExamplepbNumericEnum `json:"enum_value,omitempty"`
11-
Fixed32Value int64 `json:"fixed32_value,omitempty"`
12-
Fixed64Value string `json:"fixed64_value,omitempty"`
8+
SingleNested ABitOfEverythingNested `json:"single_nested,omitempty"`
9+
Uuid string `json:"uuid,omitempty"`
10+
Nested []ABitOfEverythingNested `json:"nested,omitempty"`
1311
FloatValue float32 `json:"float_value,omitempty"`
14-
Int32Value int32 `json:"int32_value,omitempty"`
12+
DoubleValue float64 `json:"double_value,omitempty"`
1513
Int64Value string `json:"int64_value,omitempty"`
16-
MapValue map[string]ExamplepbNumericEnum `json:"map_value,omitempty"`
17-
MappedNestedValue map[string]ABitOfEverythingNested `json:"mapped_nested_value,omitempty"`
18-
MappedStringValue map[string]string `json:"mapped_string_value,omitempty"`
19-
Nested []ABitOfEverythingNested `json:"nested,omitempty"`
20-
NonConventionalNameValue string `json:"nonConventionalNameValue,omitempty"`
21-
OneofEmpty ProtobufEmpty `json:"oneof_empty,omitempty"`
22-
OneofString string `json:"oneof_string,omitempty"`
23-
RepeatedStringValue []string `json:"repeated_string_value,omitempty"`
14+
Uint64Value string `json:"uint64_value,omitempty"`
15+
Int32Value int32 `json:"int32_value,omitempty"`
16+
Fixed64Value string `json:"fixed64_value,omitempty"`
17+
Fixed32Value int64 `json:"fixed32_value,omitempty"`
18+
BoolValue bool `json:"bool_value,omitempty"`
19+
StringValue string `json:"string_value,omitempty"`
20+
Uint32Value int64 `json:"uint32_value,omitempty"`
21+
EnumValue ExamplepbNumericEnum `json:"enum_value,omitempty"`
2422
Sfixed32Value int32 `json:"sfixed32_value,omitempty"`
2523
Sfixed64Value string `json:"sfixed64_value,omitempty"`
26-
SingleNested ABitOfEverythingNested `json:"single_nested,omitempty"`
2724
Sint32Value int32 `json:"sint32_value,omitempty"`
2825
Sint64Value string `json:"sint64_value,omitempty"`
29-
StringValue string `json:"string_value,omitempty"`
26+
RepeatedStringValue []string `json:"repeated_string_value,omitempty"`
27+
OneofEmpty ProtobufEmpty `json:"oneof_empty,omitempty"`
28+
OneofString string `json:"oneof_string,omitempty"`
29+
MapValue map[string]ExamplepbNumericEnum `json:"map_value,omitempty"`
30+
MappedStringValue map[string]string `json:"mapped_string_value,omitempty"`
31+
MappedNestedValue map[string]ABitOfEverythingNested `json:"mapped_nested_value,omitempty"`
32+
NonConventionalNameValue string `json:"nonConventionalNameValue,omitempty"`
3033
TimestampValue time.Time `json:"timestamp_value,omitempty"`
31-
Uint32Value int64 `json:"uint32_value,omitempty"`
32-
Uint64Value string `json:"uint64_value,omitempty"`
33-
Uuid string `json:"uuid,omitempty"`
3434

3535
}

examples/examplepb/a_bit_of_everything.swagger.json

Lines changed: 70 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -363,15 +363,15 @@
363363
"ABitOfEverythingNested": {
364364
"type": "object",
365365
"properties": {
366-
"amount": {
367-
"type": "integer",
368-
"format": "int64"
369-
},
370366
"name": {
371367
"type": "string",
372368
"format": "string",
373369
"description": "name is nested field."
374370
},
371+
"amount": {
372+
"type": "integer",
373+
"format": "int64"
374+
},
375375
"ok": {
376376
"$ref": "#/definitions/NestedDeepEnum"
377377
}
@@ -390,79 +390,62 @@
390390
"examplepbABitOfEverything": {
391391
"type": "object",
392392
"properties": {
393-
"bool_value": {
394-
"type": "boolean",
395-
"format": "boolean"
393+
"single_nested": {
394+
"$ref": "#/definitions/ABitOfEverythingNested"
395+
},
396+
"uuid": {
397+
"type": "string",
398+
"format": "string"
399+
},
400+
"nested": {
401+
"type": "array",
402+
"items": {
403+
"$ref": "#/definitions/ABitOfEverythingNested"
404+
}
405+
},
406+
"float_value": {
407+
"type": "number",
408+
"format": "float"
396409
},
397410
"double_value": {
398411
"type": "number",
399412
"format": "double"
400413
},
401-
"enum_value": {
402-
"$ref": "#/definitions/examplepbNumericEnum"
403-
},
404-
"fixed32_value": {
405-
"type": "integer",
414+
"int64_value": {
415+
"type": "string",
406416
"format": "int64"
407417
},
408-
"fixed64_value": {
418+
"uint64_value": {
409419
"type": "string",
410420
"format": "uint64"
411421
},
412-
"float_value": {
413-
"type": "number",
414-
"format": "float"
415-
},
416422
"int32_value": {
417423
"type": "integer",
418424
"format": "int32"
419425
},
420-
"int64_value": {
426+
"fixed64_value": {
421427
"type": "string",
422-
"format": "int64"
423-
},
424-
"map_value": {
425-
"type": "object",
426-
"additionalProperties": {
427-
"$ref": "#/definitions/examplepbNumericEnum"
428-
}
429-
},
430-
"mapped_nested_value": {
431-
"type": "object",
432-
"additionalProperties": {
433-
"$ref": "#/definitions/ABitOfEverythingNested"
434-
}
428+
"format": "uint64"
435429
},
436-
"mapped_string_value": {
437-
"type": "object",
438-
"additionalProperties": {
439-
"type": "string",
440-
"format": "string"
441-
}
430+
"fixed32_value": {
431+
"type": "integer",
432+
"format": "int64"
442433
},
443-
"nested": {
444-
"type": "array",
445-
"items": {
446-
"$ref": "#/definitions/ABitOfEverythingNested"
447-
}
434+
"bool_value": {
435+
"type": "boolean",
436+
"format": "boolean"
448437
},
449-
"nonConventionalNameValue": {
438+
"string_value": {
450439
"type": "string",
451440
"format": "string"
452441
},
453-
"oneof_empty": {
454-
"$ref": "#/definitions/protobufEmpty"
455-
},
456-
"oneof_string": {
457-
"type": "string",
458-
"format": "string"
442+
"uint32_value": {
443+
"type": "integer",
444+
"format": "int64",
445+
"title": "TODO(yugui) add bytes_value"
459446
},
460-
"repeated_string_value": {
461-
"type": "array",
462-
"items": {
463-
"type": "string",
464-
"format": "string"
465-
}
447+
"enum_value": {
448+
"$ref": "#/definitions/examplepbNumericEnum"
466449
},
467450
"sfixed32_value": {
468451
"type": "integer",
@@ -472,9 +455,6 @@
472455
"type": "string",
473456
"format": "int64"
474457
},
475-
"single_nested": {
476-
"$ref": "#/definitions/ABitOfEverythingNested"
477-
},
478458
"sint32_value": {
479459
"type": "integer",
480460
"format": "int32"
@@ -483,26 +463,46 @@
483463
"type": "string",
484464
"format": "int64"
485465
},
486-
"string_value": {
466+
"repeated_string_value": {
467+
"type": "array",
468+
"items": {
469+
"type": "string",
470+
"format": "string"
471+
}
472+
},
473+
"oneof_empty": {
474+
"$ref": "#/definitions/protobufEmpty"
475+
},
476+
"oneof_string": {
487477
"type": "string",
488478
"format": "string"
489479
},
490-
"timestamp_value": {
491-
"type": "string",
492-
"format": "date-time"
480+
"map_value": {
481+
"type": "object",
482+
"additionalProperties": {
483+
"$ref": "#/definitions/examplepbNumericEnum"
484+
}
493485
},
494-
"uint32_value": {
495-
"type": "integer",
496-
"format": "int64",
497-
"title": "TODO(yugui) add bytes_value"
486+
"mapped_string_value": {
487+
"type": "object",
488+
"additionalProperties": {
489+
"type": "string",
490+
"format": "string"
491+
}
498492
},
499-
"uint64_value": {
500-
"type": "string",
501-
"format": "uint64"
493+
"mapped_nested_value": {
494+
"type": "object",
495+
"additionalProperties": {
496+
"$ref": "#/definitions/ABitOfEverythingNested"
497+
}
502498
},
503-
"uuid": {
499+
"nonConventionalNameValue": {
504500
"type": "string",
505501
"format": "string"
502+
},
503+
"timestamp_value": {
504+
"type": "string",
505+
"format": "date-time"
506506
}
507507
},
508508
"title": "Intentionaly complicated message type to cover much features of Protobuf.\nNEXT ID: 27"

protoc-gen-swagger/genswagger/template.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ func renderMessagesAsDefinition(messages messageMap, d swaggerDefinitionsObject,
6262
schemaCore: schemaCore{
6363
Type: "object",
6464
},
65-
Properties: make(map[string]swaggerSchemaObject),
65+
Properties: make(swaggerSchemaObjectProperties, 0),
6666
}
6767
msgComments := protoComments(reg, msg.File, msg.Outers, "MessageType", int32(msg.Index))
6868
if err := updateSwaggerDataFromComments(&schema, msgComments); err != nil {
@@ -78,7 +78,7 @@ func renderMessagesAsDefinition(messages messageMap, d swaggerDefinitionsObject,
7878
panic(err)
7979
}
8080

81-
schema.Properties[f.GetName()] = fieldValue
81+
schema.Properties = append(schema.Properties, keyVal{f.GetName(), fieldValue})
8282
}
8383
d[fullyQualifiedNameToSwaggerName(msg.FQMN(), reg)] = schema
8484
}

protoc-gen-swagger/genswagger/types.go

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package genswagger
22

33
import (
4+
"bytes"
5+
"encoding/json"
6+
47
"github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway/descriptor"
58
)
69

@@ -116,13 +119,44 @@ type swaggerResponseObject struct {
116119
Schema swaggerSchemaObject `json:"schema"`
117120
}
118121

122+
type keyVal struct {
123+
Key string
124+
Value interface{}
125+
}
126+
127+
type swaggerSchemaObjectProperties []keyVal
128+
129+
func (op swaggerSchemaObjectProperties) MarshalJSON() ([]byte, error) {
130+
var buf bytes.Buffer
131+
buf.WriteString("{")
132+
for i, kv := range op {
133+
if i != 0 {
134+
buf.WriteString(",")
135+
}
136+
key, err := json.Marshal(kv.Key)
137+
if err != nil {
138+
return nil, err
139+
}
140+
buf.Write(key)
141+
buf.WriteString(":")
142+
val, err := json.Marshal(kv.Value)
143+
if err != nil {
144+
return nil, err
145+
}
146+
buf.Write(val)
147+
}
148+
149+
buf.WriteString("}")
150+
return buf.Bytes(), nil
151+
}
152+
119153
// http://swagger.io/specification/#schemaObject
120154
type swaggerSchemaObject struct {
121155
schemaCore
122156
// Properties can be recursively defined
123-
Properties map[string]swaggerSchemaObject `json:"properties,omitempty"`
124-
AdditionalProperties *swaggerSchemaObject `json:"additionalProperties,omitempty"`
125-
Items *swaggerItemsObject `json:"items,omitempty"`
157+
Properties swaggerSchemaObjectProperties `json:"properties,omitempty"`
158+
AdditionalProperties *swaggerSchemaObject `json:"additionalProperties,omitempty"`
159+
Items *swaggerItemsObject `json:"items,omitempty"`
126160

127161
// If the item is an enumeration include a list of all the *NAMES* of the
128162
// enum values. I'm not sure how well this will work but assuming all enums

0 commit comments

Comments
 (0)