From 254d19aa6d6ca9508995a7c1f95c27eedb3ef235 Mon Sep 17 00:00:00 2001 From: Jordan Wu <101218661+jordan-definitive@users.noreply.github.com> Date: Mon, 15 Apr 2024 15:44:13 -0700 Subject: [PATCH] openapi3: keep oneOf context in markSchemaErrorKey (#940) --- openapi3/schema.go | 3 +- openapi3/schema_issue940_test.go | 67 ++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 openapi3/schema_issue940_test.go diff --git a/openapi3/schema.go b/openapi3/schema.go index ae28afef7..eafb82740 100644 --- a/openapi3/schema.go +++ b/openapi3/schema.go @@ -2122,7 +2122,8 @@ func markSchemaErrorKey(err error, key string) error { var me multiErrorForOneOf if errors.As(err, &me) { - err = me.Unwrap() + origin := me.Unwrap() + _ = markSchemaErrorKey(origin, key) } if v, ok := err.(*SchemaError); ok { diff --git a/openapi3/schema_issue940_test.go b/openapi3/schema_issue940_test.go new file mode 100644 index 000000000..ffcba7be1 --- /dev/null +++ b/openapi3/schema_issue940_test.go @@ -0,0 +1,67 @@ +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()) + +}