Skip to content

Commit

Permalink
fix drilling down additionalProperties in the boolean case (#378)
Browse files Browse the repository at this point in the history
  • Loading branch information
fenollp committed Jun 23, 2021
1 parent 5ffbbe3 commit d308378
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 11 deletions.
1 change: 1 addition & 0 deletions .github/workflows/go.yml
Expand Up @@ -69,6 +69,7 @@ jobs:
cd openapi3/testdata
go get -u -v github.com/getkin/kin-openapi
go test -tags with_embed ./...
git --no-pager diff && git checkout -- .
cd -
if: matrix.go != '1.14'
- if: runner.os == 'Linux'
Expand Down
60 changes: 60 additions & 0 deletions openapi3/issue376_test.go
@@ -1,6 +1,7 @@
package openapi3

import (
"fmt"
"testing"

"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -40,3 +41,62 @@ info:

require.Equal(t, "string", doc.Components.Schemas["schema2"].Value.Properties["prop"].Value.Type)
}

func TestMultijsonTagSerialization(t *testing.T) {
spec := []byte(`
openapi: 3.0.0
components:
schemas:
unset:
type: number
#empty-object:
# TODO additionalProperties: {}
object:
additionalProperties: {type: string}
boolean:
additionalProperties: false
paths: {}
info:
title: An API
version: 1.2.3.4
`)

loader := NewLoader()

doc, err := loader.LoadFromData(spec)
require.NoError(t, err)

err = doc.Validate(loader.Context)
require.NoError(t, err)

for propName, propSchema := range doc.Components.Schemas {
ap := propSchema.Value.AdditionalProperties
apa := propSchema.Value.AdditionalPropertiesAllowed

encoded, err := propSchema.MarshalJSON()
require.NoError(t, err)
require.Equal(t, string(encoded), map[string]string{
"unset": `{"type":"number"}`,
// TODO: "empty-object":`{"additionalProperties":{}}`,
"object": `{"additionalProperties":{"type":"string"}}`,
"boolean": `{"additionalProperties":false}`,
}[propName])

if propName == "unset" {
require.True(t, ap == nil && apa == nil)
continue
}

apStr := ""
if ap != nil {
apStr = fmt.Sprintf("{Ref:%s Value.Type:%v}", (*ap).Ref, (*ap).Value.Type)
}
apaStr := ""
if apa != nil {
apaStr = fmt.Sprintf("%v", *apa)
}

require.Truef(t, (ap != nil && apa == nil) || (ap == nil && apa != nil),
"%s: isnil(%s) xor isnil(%s)", propName, apaStr, apStr)
}
}
6 changes: 3 additions & 3 deletions openapi3/loader.go
Expand Up @@ -351,10 +351,10 @@ func (loader *Loader) resolveComponent(
func drillIntoField(cursor interface{}, fieldName string) (interface{}, error) {
// Special case due to multijson
if s, ok := cursor.(*SchemaRef); ok && fieldName == "additionalProperties" {
if ap := s.Value.AdditionalProperties; ap != nil {
return ap, nil
if ap := s.Value.AdditionalPropertiesAllowed; ap != nil {
return *ap, nil
}
return s.Value.AdditionalPropertiesAllowed, nil
return s.Value.AdditionalProperties, nil
}

switch val := reflect.Indirect(reflect.ValueOf(cursor)); val.Kind() {
Expand Down
15 changes: 7 additions & 8 deletions openapi3/schema.go
Expand Up @@ -109,8 +109,6 @@ type Schema struct {
Example interface{} `json:"example,omitempty" yaml:"example,omitempty"`
ExternalDocs *ExternalDocs `json:"externalDocs,omitempty" yaml:"externalDocs,omitempty"`

// Object-related, here for struct compactness
AdditionalPropertiesAllowed *bool `multijson:"additionalProperties,omitempty" json:"-" yaml:"-"`
// Array-related, here for struct compactness
UniqueItems bool `json:"uniqueItems,omitempty" yaml:"uniqueItems,omitempty"`
// Number-related, here for struct compactness
Expand Down Expand Up @@ -141,12 +139,13 @@ type Schema struct {
Items *SchemaRef `json:"items,omitempty" yaml:"items,omitempty"`

// Object
Required []string `json:"required,omitempty" yaml:"required,omitempty"`
Properties Schemas `json:"properties,omitempty" yaml:"properties,omitempty"`
MinProps uint64 `json:"minProperties,omitempty" yaml:"minProperties,omitempty"`
MaxProps *uint64 `json:"maxProperties,omitempty" yaml:"maxProperties,omitempty"`
AdditionalProperties *SchemaRef `multijson:"additionalProperties,omitempty" json:"-" yaml:"-"`
Discriminator *Discriminator `json:"discriminator,omitempty" yaml:"discriminator,omitempty"`
Required []string `json:"required,omitempty" yaml:"required,omitempty"`
Properties Schemas `json:"properties,omitempty" yaml:"properties,omitempty"`
MinProps uint64 `json:"minProperties,omitempty" yaml:"minProperties,omitempty"`
MaxProps *uint64 `json:"maxProperties,omitempty" yaml:"maxProperties,omitempty"`
AdditionalPropertiesAllowed *bool `multijson:"additionalProperties,omitempty" json:"-" yaml:"-"` // In this order...
AdditionalProperties *SchemaRef `multijson:"additionalProperties,omitempty" json:"-" yaml:"-"` // ...for multijson
Discriminator *Discriminator `json:"discriminator,omitempty" yaml:"discriminator,omitempty"`
}

var _ jsonpointer.JSONPointable = (*Schema)(nil)
Expand Down

0 comments on commit d308378

Please sign in to comment.