Skip to content

Commit

Permalink
openapi3: keep oneOf context in markSchemaErrorKey (getkin#940)
Browse files Browse the repository at this point in the history
  • Loading branch information
jordan-wu-97 committed Apr 16, 2024
1 parent fb0a24e commit a3858e8
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 5 deletions.
12 changes: 7 additions & 5 deletions openapi3/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -2119,14 +2119,16 @@ type SchemaError struct {
var _ interface{ Unwrap() error } = SchemaError{}

func markSchemaErrorKey(err error, key string) error {
var me multiErrorForOneOf

if errors.As(err, &me) {
err = me.Unwrap()
}

if v, ok := err.(*SchemaError); ok {
v.reversePath = append(v.reversePath, key)
if v.Origin != nil {
if unwrapped := errors.Unwrap(v.Origin); unwrapped != nil {
if me, ok := unwrapped.(multiErrorForOneOf); ok {
_ = markSchemaErrorKey(MultiError(me), key)
}
}
}
return v
}
if v, ok := err.(MultiError); ok {
Expand Down
72 changes: 72 additions & 0 deletions openapi3/schema_issue940_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package openapi3

import (
"context"
"encoding/json"
"errors"
"testing"

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

func TestOneOfErrorPreserved(t *testing.T) {

SchemaErrorDetailsDisabled = true
defer func() { SchemaErrorDetailsDisabled = false }()

// language=json
raw := `
{
"foo": [ "bar" ]
}
`

// language=json
schema := `
{
"type": "object",
"properties": {
"foo": {
"oneOf": [
{
"type": "number"
},
{
"type": "string"
}
]
}
}
}
`

s := NewSchema()
err := s.UnmarshalJSON([]byte(schema))
require.NoError(t, err)
err = s.Validate(context.Background())
require.NoError(t, err)

obj := make(map[string]interface{})
err = json.Unmarshal([]byte(raw), &obj)
require.NoError(t, err)

err = s.VisitJSON(obj, MultiErrors())
require.Error(t, err)

var multiError MultiError
ok := errors.As(err, &multiError)
require.True(t, ok)
var schemaErr *SchemaError
ok = errors.As(multiError[0], &schemaErr)
require.True(t, ok)

require.Equal(t, "oneOf", schemaErr.SchemaField)
require.Equal(t, `value doesn't match any schema from "oneOf"`, schemaErr.Reason)
require.Equal(t, `Error at "/foo": doesn't match schema due to: value must be a number Or value must be a string`, schemaErr.Error())

var me multiErrorForOneOf
ok = errors.As(err, &me)
require.True(t, ok)
require.Equal(t, `Error at "/foo": value must be a number`, me[0].Error())
require.Equal(t, `Error at "/foo": value must be a string`, me[1].Error())
}

0 comments on commit a3858e8

Please sign in to comment.