Skip to content

Commit

Permalink
openapi3: allow YAML-marshaling invalid specs (#977)
Browse files Browse the repository at this point in the history
* openapi3: allow YAML-marshaling invalid specs

Signed-off-by: Pierre Fenoll <[email protected]>

* fixes

Signed-off-by: Pierre Fenoll <[email protected]>

---------

Signed-off-by: Pierre Fenoll <[email protected]>
  • Loading branch information
fenollp authored Jul 5, 2024
1 parent 4144c56 commit 2692f43
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 6 deletions.
2 changes: 1 addition & 1 deletion .github/docs/openapi3.txt
Original file line number Diff line number Diff line change
Expand Up @@ -645,7 +645,7 @@ type Info struct {
func (info Info) MarshalJSON() ([]byte, error)
MarshalJSON returns the JSON encoding of Info.

func (info Info) MarshalYAML() (any, error)
func (info *Info) MarshalYAML() (any, error)
MarshalYAML returns the YAML encoding of Info.

func (info *Info) UnmarshalJSON(data []byte) error
Expand Down
7 changes: 7 additions & 0 deletions maps.sh
Original file line number Diff line number Diff line change
Expand Up @@ -155,9 +155,16 @@ EOF


maplike_UnMarsh() {
if [[ "$type" != '*'* ]]; then
echo "TODO: impl non-pointer receiver YAML Marshaler"
exit 2
fi
cat <<EOF >>"$maplike"
// MarshalYAML returns the YAML encoding of ${type#'*'}.
func (${name} ${type}) MarshalYAML() (any, error) {
if ${name} == nil {
return nil, nil
}
m := make(map[string]any, ${name}.Len()+len(${name}.Extensions))
for k, v := range ${name}.Extensions {
m[k] = v
Expand Down
5 changes: 4 additions & 1 deletion openapi3/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ func (info Info) MarshalJSON() ([]byte, error) {
}

// MarshalYAML returns the YAML encoding of Info.
func (info Info) MarshalYAML() (any, error) {
func (info *Info) MarshalYAML() (any, error) {
if info == nil {
return nil, nil
}
m := make(map[string]any, 6+len(info.Extensions))
for k, v := range info.Extensions {
m[k] = v
Expand Down
66 changes: 66 additions & 0 deletions openapi3/issue972_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package openapi3

import (
"testing"

"github.com/stretchr/testify/assert"
"gopkg.in/yaml.v3"
)

func TestIssue972(t *testing.T) {
type testcase struct {
spec string
validationErrorContains string
}

base := `
openapi: 3.0.2
paths: {}
components: {}
`

for _, tc := range []testcase{{
spec: base,
validationErrorContains: "invalid info: must be an object",
}, {
spec: base + `
info:
title: "Hello World REST APIs"
version: "1.0"
`,
}, {
spec: base + `
info: null
`,
validationErrorContains: "invalid info: must be an object",
}, {
spec: base + `
info: {}
`,
validationErrorContains: "invalid info: value of version must be a non-empty string",
}, {
spec: base + `
info:
title: "Hello World REST APIs"
`,
validationErrorContains: "invalid info: value of version must be a non-empty string",
}} {
t.Logf("spec: %s", tc.spec)

loader := &Loader{}
doc, err := loader.LoadFromData([]byte(tc.spec))
assert.NoError(t, err)
assert.NotNil(t, doc)

err = doc.Validate(loader.Context)
if e := tc.validationErrorContains; e != "" {
assert.ErrorContains(t, err, e)
} else {
assert.NoError(t, err)
}

txt, err := yaml.Marshal(doc)
assert.NoError(t, err)
assert.NotEmpty(t, txt)
}
}
3 changes: 1 addition & 2 deletions openapi3/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -1140,8 +1140,7 @@ func (loader *Loader) resolvePathItemRef(doc *T, pathItem *PathItem, documentPat
*pathItem = p
} else {
var resolved PathItem
doc, documentPath, err = loader.resolveComponent(doc, ref, documentPath, &resolved)
if err != nil {
if doc, documentPath, err = loader.resolveComponent(doc, ref, documentPath, &resolved); err != nil {
if err == errMUSTPathItem {
return nil
}
Expand Down
9 changes: 9 additions & 0 deletions openapi3/maplike.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ func (responses Responses) JSONLookup(token string) (any, error) {

// MarshalYAML returns the YAML encoding of Responses.
func (responses *Responses) MarshalYAML() (any, error) {
if responses == nil {
return nil, nil
}
m := make(map[string]any, responses.Len()+len(responses.Extensions))
for k, v := range responses.Extensions {
m[k] = v
Expand Down Expand Up @@ -206,6 +209,9 @@ func (callback Callback) JSONLookup(token string) (any, error) {

// MarshalYAML returns the YAML encoding of Callback.
func (callback *Callback) MarshalYAML() (any, error) {
if callback == nil {
return nil, nil
}
m := make(map[string]any, callback.Len()+len(callback.Extensions))
for k, v := range callback.Extensions {
m[k] = v
Expand Down Expand Up @@ -334,6 +340,9 @@ func (paths Paths) JSONLookup(token string) (any, error) {

// MarshalYAML returns the YAML encoding of Paths.
func (paths *Paths) MarshalYAML() (any, error) {
if paths == nil {
return nil, nil
}
m := make(map[string]any, paths.Len()+len(paths.Extensions))
for k, v := range paths.Extensions {
m[k] = v
Expand Down
3 changes: 3 additions & 0 deletions openapi3/openapi3.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ func (doc *T) MarshalJSON() ([]byte, error) {

// MarshalYAML returns the YAML encoding of T.
func (doc *T) MarshalYAML() (any, error) {
if doc == nil {
return nil, nil
}
m := make(map[string]any, 4+len(doc.Extensions))
for k, v := range doc.Extensions {
m[k] = v
Expand Down
4 changes: 2 additions & 2 deletions openapi3/schema_formats_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,13 +169,13 @@ func TestNumberFormats(t *testing.T) {
}
DefineNumberFormatValidator("lessThan10", NewCallbackValidator(func(value float64) error {
if value >= 10 {
return fmt.Errorf("not less than 10")
return errors.New("not less than 10")
}
return nil
}))
DefineIntegerFormatValidator("odd", NewCallbackValidator(func(value int64) error {
if value%2 == 0 {
return fmt.Errorf("not odd")
return errors.New("not odd")
}
return nil
}))
Expand Down

0 comments on commit 2692f43

Please sign in to comment.