Skip to content

Commit

Permalink
handle digits in $ref.s (#213)
Browse files Browse the repository at this point in the history
  • Loading branch information
fenollp authored May 24, 2020
1 parent 0d3735e commit eac89ec
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 6 deletions.
4 changes: 2 additions & 2 deletions openapi2conv/openapi2_conv.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/getkin/kin-openapi/openapi3"
)

// ToV3Swagger converts an OpenAPIv2 spec to an OpenAPIv3 spec
func ToV3Swagger(swagger *openapi2.Swagger) (*openapi3.Swagger, error) {
result := &openapi3.Swagger{
OpenAPI: "3.0.2",
Expand Down Expand Up @@ -396,8 +397,7 @@ func FromV3Swagger(swagger *openapi3.Swagger) (*openapi2.Swagger, error) {
}
result.Parameters = map[string]*openapi2.Parameter{}
for name, param := range swagger.Components.Parameters {
result.Parameters[name], err = FromV3Parameter(param)
if err != nil {
if result.Parameters[name], err = FromV3Parameter(param); err != nil {
return nil, err
}
}
Expand Down
20 changes: 16 additions & 4 deletions openapi3/swagger_loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"net/url"
"path"
"reflect"
"strconv"
"strings"

"github.com/ghodss/yaml"
Expand Down Expand Up @@ -285,16 +286,25 @@ func (swaggerLoader *SwaggerLoader) resolveComponent(swagger *Swagger, ref strin
}

func drillIntoSwaggerField(cursor interface{}, fieldName string) (interface{}, error) {
val := reflect.Indirect(reflect.ValueOf(cursor))

switch val.Kind() {
switch val := reflect.Indirect(reflect.ValueOf(cursor)); val.Kind() {
case reflect.Map:
elementValue := val.MapIndex(reflect.ValueOf(fieldName))
if !elementValue.IsValid() {
return nil, fmt.Errorf("Map key not found: %v", fieldName)
}
return elementValue.Interface(), nil

case reflect.Slice:
i, err := strconv.ParseUint(fieldName, 10, 32)
if err != nil {
return nil, err
}
index := int(i)
if index >= val.Len() {
return nil, errors.New("slice index out of bounds")
}
return val.Index(index).Interface(), nil

case reflect.Struct:
for i := 0; i < val.NumField(); i++ {
field := val.Type().Field(i)
Expand All @@ -311,8 +321,10 @@ func drillIntoSwaggerField(cursor interface{}, fieldName string) (interface{}, e
}
// give up
return nil, fmt.Errorf("Struct field not found: %v", fieldName)

default:
return nil, errors.New("not a map, slice nor struct")
}
return nil, errors.New("Not a map or struct")
}

func (swaggerLoader *SwaggerLoader) resolveRefSwagger(swagger *Swagger, ref string, path *url.URL) (*Swagger, string, *url.URL, error) {
Expand Down
95 changes: 95 additions & 0 deletions openapi3/swagger_loader_issue212_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package openapi3

import (
"encoding/json"
"testing"

"github.com/stretchr/testify/require"
)

func TestIssue212(t *testing.T) {
spec := `
openapi: 3.0.1
info:
title: 'test'
version: 1.0.0
servers:
- url: /api
paths:
/available-products:
get:
operationId: getAvailableProductCollection
responses:
"200":
description: test
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/AvailableProduct"
components:
schemas:
AvailableProduct:
type: object
properties:
id:
type: string
type:
type: string
name:
type: string
media:
type: object
properties:
documents:
type: array
items:
allOf:
- $ref: "#/components/schemas/AvailableProduct/properties/previewImage/allOf/0"
- type: object
properties:
uri:
type: string
pattern: ^\/documents\/[0-9a-f]{64}$
previewImage:
allOf:
- type: object
required:
- id
- uri
properties:
id:
type: string
uri:
type: string
- type: object
properties:
uri:
type: string
pattern: ^\/images\/[0-9a-f]{64}$
`

loader := NewSwaggerLoader()
doc, err := loader.LoadSwaggerFromData([]byte(spec))
require.NoError(t, err)
err = doc.Validate(loader.Context)
require.NoError(t, err)

expected, err := json.Marshal(&Schema{
Type: "object",
Required: []string{"id", "uri"},
Properties: map[string]*SchemaRef{
"id": {Value: &Schema{Type: "string"}},
"uri": {Value: &Schema{Type: "string"}},
},
},
)
require.NoError(t, err)
got, err := json.Marshal(doc.Components.Schemas["AvailableProduct"].Value.Properties["media"].Value.Properties["documents"].Value.Items.Value.AllOf[0].Value)
require.NoError(t, err)

require.Equal(t, expected, got)
}

0 comments on commit eac89ec

Please sign in to comment.