Skip to content

Commit ebbf60d

Browse files
authored
fix: setting defaults for oneOf and anyOf (#690)
1 parent b4b41f3 commit ebbf60d

File tree

2 files changed

+125
-8
lines changed

2 files changed

+125
-8
lines changed

openapi3/schema.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -934,10 +934,6 @@ func (schema *Schema) visitSetOperations(settings *schemaValidationSettings, val
934934
matchedOneOfIdx = 0
935935
tempValue = value
936936
)
937-
// make a deep copy to protect origin value from being injected default value that defined in mismatched oneOf schema
938-
if settings.asreq || settings.asrep {
939-
tempValue = deepcopy.Copy(value)
940-
}
941937
for idx, item := range v {
942938
v := item.Value
943939
if v == nil {
@@ -948,6 +944,11 @@ func (schema *Schema) visitSetOperations(settings *schemaValidationSettings, val
948944
continue
949945
}
950946

947+
// make a deep copy to protect origin value from being injected default value that defined in mismatched oneOf schema
948+
if settings.asreq || settings.asrep {
949+
tempValue = deepcopy.Copy(value)
950+
}
951+
951952
if err := v.visitJSON(settings, tempValue); err != nil {
952953
validationErrors = append(validationErrors, err)
953954
continue
@@ -990,15 +991,15 @@ func (schema *Schema) visitSetOperations(settings *schemaValidationSettings, val
990991
matchedAnyOfIdx = 0
991992
tempValue = value
992993
)
993-
// make a deep copy to protect origin value from being injected default value that defined in mismatched anyOf schema
994-
if settings.asreq || settings.asrep {
995-
tempValue = deepcopy.Copy(value)
996-
}
997994
for idx, item := range v {
998995
v := item.Value
999996
if v == nil {
1000997
return foundUnresolvedRef(item.Ref)
1001998
}
999+
// make a deep copy to protect origin value from being injected default value that defined in mismatched anyOf schema
1000+
if settings.asreq || settings.asrep {
1001+
tempValue = deepcopy.Copy(value)
1002+
}
10021003
if err := v.visitJSON(settings, tempValue); err == nil {
10031004
ok = true
10041005
matchedAnyOfIdx = idx

openapi3filter/validate_set_default_test.go

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,70 @@ func TestValidateRequestBodyAndSetDefault(t *testing.T) {
317317
}
318318
}
319319
]
320+
},
321+
"contact": {
322+
"oneOf": [
323+
{
324+
"type": "object",
325+
"required": ["email"],
326+
"properties": {
327+
"email": {
328+
"type": "string"
329+
},
330+
"allow_image": {
331+
"type": "boolean",
332+
"default": true
333+
}
334+
},
335+
"additionalProperties": false
336+
},
337+
{
338+
"type": "object",
339+
"required": ["phone"],
340+
"properties": {
341+
"phone": {
342+
"type": "string"
343+
},
344+
"allow_text": {
345+
"type": "boolean",
346+
"default": false
347+
}
348+
},
349+
"additionalProperties": false
350+
}
351+
]
352+
},
353+
"contact2": {
354+
"anyOf": [
355+
{
356+
"type": "object",
357+
"required": ["email"],
358+
"properties": {
359+
"email": {
360+
"type": "string"
361+
},
362+
"allow_image": {
363+
"type": "boolean",
364+
"default": true
365+
}
366+
},
367+
"additionalProperties": false
368+
},
369+
{
370+
"type": "object",
371+
"required": ["phone"],
372+
"properties": {
373+
"phone": {
374+
"type": "string"
375+
},
376+
"allow_text": {
377+
"type": "boolean",
378+
"default": false
379+
}
380+
},
381+
"additionalProperties": false
382+
}
383+
]
320384
}
321385
}
322386
}
@@ -358,6 +422,10 @@ func TestValidateRequestBodyAndSetDefault(t *testing.T) {
358422
FBLink string `json:"fb_link,omitempty"`
359423
TWLink string `json:"tw_link,omitempty"`
360424
}
425+
type contact struct {
426+
Email string `json:"email,omitempty"`
427+
Phone string `json:"phone,omitempty"`
428+
}
361429
type body struct {
362430
ID string `json:"id,omitempty"`
363431
Name string `json:"name,omitempty"`
@@ -367,6 +435,8 @@ func TestValidateRequestBodyAndSetDefault(t *testing.T) {
367435
Filters []filter `json:"filters,omitempty"`
368436
SocialNetwork *socialNetwork `json:"social_network,omitempty"`
369437
SocialNetwork2 *socialNetwork `json:"social_network_2,omitempty"`
438+
Contact *contact `json:"contact,omitempty"`
439+
Contact2 *contact `json:"contact2,omitempty"`
370440
}
371441

372442
testCases := []struct {
@@ -656,6 +726,52 @@ func TestValidateRequestBodyAndSetDefault(t *testing.T) {
656726
"platform": "facebook",
657727
"fb_link": "www.facebook.com"
658728
}
729+
}
730+
`, body)
731+
},
732+
},
733+
{
734+
name: "contact(oneOf)",
735+
body: body{
736+
ID: "bt6kdc3d0cvp6u8u3ft0",
737+
Contact: &contact{
738+
Phone: "123456",
739+
},
740+
},
741+
bodyAssertion: func(t *testing.T, body string) {
742+
require.JSONEq(t, `
743+
{
744+
"id": "bt6kdc3d0cvp6u8u3ft0",
745+
"name": "default",
746+
"code": 123,
747+
"all": false,
748+
"contact": {
749+
"phone": "123456",
750+
"allow_text": false
751+
}
752+
}
753+
`, body)
754+
},
755+
},
756+
{
757+
name: "contact(anyOf)",
758+
body: body{
759+
ID: "bt6kdc3d0cvp6u8u3ft0",
760+
Contact2: &contact{
761+
Phone: "123456",
762+
},
763+
},
764+
bodyAssertion: func(t *testing.T, body string) {
765+
require.JSONEq(t, `
766+
{
767+
"id": "bt6kdc3d0cvp6u8u3ft0",
768+
"name": "default",
769+
"code": 123,
770+
"all": false,
771+
"contact2": {
772+
"phone": "123456",
773+
"allow_text": false
774+
}
659775
}
660776
`, body)
661777
},

0 commit comments

Comments
 (0)