Skip to content

Commit

Permalink
Add support for the x-order extension.
Browse files Browse the repository at this point in the history
Fix for deepmap#458.
Can be used when you need to set the order of fields in the model:
```yaml
    NewPet:
      type: object
      required:
        - name
      properties:
        name:
          type: string
          x-order: 1
        tag:
          type: string
          x-order: 2
```
  • Loading branch information
psyhatter committed Jun 14, 2022
1 parent 7da811e commit 2d3fe35
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 4 deletions.
28 changes: 28 additions & 0 deletions README.md
Expand Up @@ -533,6 +533,34 @@ which help you to use the various OpenAPI 3 Authentication mechanism.
```
Name string `json:"name" tag1:"value1" tag2:"value2"`
```
- `x-order`: specifies the order of the fields in the structure. It allows you to specify the order
of the fields in the generated structure and will override any default value. This extended
property is not supported in all parts of OpenAPI, so check the specification to see where it is
allowed. Swagger validation tools will flag misuse of this property.

```yaml
DateInterval:
type: object
required:
- name
properties:
start:
type: string
format: date
x-order: 1
end:
type: string
format: date
x-order: 2
```
In the example above, struct will be declared as:

```go
type DateInterval struct {
Start *openapi_types.Date `json:"start,omitempty"`
End *openapi_types.Date `json:"end,omitempty"`
}
```



Expand Down
39 changes: 35 additions & 4 deletions pkg/codegen/utils.go
Expand Up @@ -14,13 +14,15 @@
package codegen

import (
"encoding/json"
"fmt"
"net/url"
"regexp"
"sort"
"strconv"
"strings"
"unicode"
"unsafe"

"github.com/getkin/kin-openapi/openapi3"
)
Expand Down Expand Up @@ -89,13 +91,42 @@ func ToCamelCase(str string) string {
// This function returns the keys of the given SchemaRef dictionary in sorted
// order, since Golang scrambles dictionary keys
func SortedSchemaKeys(dict map[string]*openapi3.SchemaRef) []string {
keys := make([]string, len(dict))
i := 0
for key := range dict {
keys[i] = key
keys := make([]string, len(dict))
orders := make(map[string]int64, len(dict))

for key, v := range dict {
keys[i], orders[key] = key, int64(len(dict))
i++

if v == nil || v.Value == nil {
continue
}

ext := v.Value.Extensions["x-order"]
if ext == nil {
continue
}

var xOrder string
if b, ok := ext.(json.RawMessage); ok {
xOrder = *(*string)(unsafe.Pointer(&b))
} else { // not sure if this is possible.
xOrder = fmt.Sprint(ext)
}

order, err := strconv.ParseInt(xOrder, 10, 0)
if err == nil {
orders[key] = order
}
}
sort.Strings(keys)

sort.Slice(keys, func(i, j int) bool {
if i, j := orders[keys[i]], orders[keys[j]]; i != j {
return i < j
}
return keys[i] < keys[j]
})
return keys
}

Expand Down
28 changes: 28 additions & 0 deletions pkg/codegen/utils_test.go
Expand Up @@ -14,6 +14,8 @@
package codegen

import (
"encoding/json"
"strconv"
"testing"

"github.com/getkin/kin-openapi/openapi3"
Expand Down Expand Up @@ -43,6 +45,32 @@ func TestSortedSchemaKeys(t *testing.T) {
assert.EqualValues(t, expected, SortedSchemaKeys(dict), "Keys are not sorted properly")
}

func TestSortedSchemaKeysWithXOrder(t *testing.T) {
withOrder := func(i int) *openapi3.SchemaRef {
return &openapi3.SchemaRef{
Value: &openapi3.Schema{
ExtensionProps: openapi3.ExtensionProps{
Extensions: map[string]interface{}{"x-order": json.RawMessage(strconv.Itoa(i))},
},
},
}
}
dict := map[string]*openapi3.SchemaRef{
"minusHundredth": withOrder(-100),
"minusTenth": withOrder(-10),
"zero": withOrder(0),
"first": withOrder(1),
"middleA": nil,
"middleB": nil,
"middleC": nil,
"last": withOrder(100),
}

expected := []string{"minusHundredth", "minusTenth", "zero", "first", "middleA", "middleB", "middleC", "last"}

assert.EqualValues(t, expected, SortedSchemaKeys(dict), "Keys are not sorted properly")
}

func TestSortedPathsKeys(t *testing.T) {
dict := openapi3.Paths{
"f": nil,
Expand Down

0 comments on commit 2d3fe35

Please sign in to comment.