Skip to content

Commit 342d482

Browse files
authored
Merge pull request #219 from aznan2/master
Fix for oneOf when not all properties are matched
2 parents 268413b + ec9f933 commit 342d482

File tree

5 files changed

+158
-17
lines changed

5 files changed

+158
-17
lines changed

src/main/java/com/networknt/schema/PropertiesValidator.java

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public Set<ValidationMessage> validate(JsonNode node, JsonNode rootNode, String
4848
state = new ValidatorState();
4949
validatorState.set(state);
5050
}
51-
51+
5252
for (Map.Entry<String, JsonSchema> entry : schemas.entrySet()) {
5353
JsonSchema propertySchema = entry.getValue();
5454
JsonNode propertyNode = node.get(entry.getKey());
@@ -62,27 +62,32 @@ public Set<ValidationMessage> validate(JsonNode node, JsonNode rootNode, String
6262
}
6363
// reset the complex validator for child element validation, and reset it after the return from the recursive call
6464
state.setComplexValidator(false);
65-
65+
6666
//validate the child element(s)
67-
errors.addAll(propertySchema.validate(propertyNode, rootNode, at + "." + entry.getKey()));
68-
69-
// reset the complex flag to the original value before the recursive call
70-
state.setComplexValidator(isComplex);
71-
// if this was a complex validator, the node has matched and has been validated
67+
errors.addAll(propertySchema.validate(propertyNode, rootNode, at + "." + entry.getKey()));
68+
69+
// reset the complex flag to the original value before the recursive call
70+
state.setComplexValidator(isComplex);
71+
// if this was a complex validator, the node has matched and has been validated
7272
if(state.isComplexValidator()) {
7373
state.setMatchedNode(true);
7474
}
7575
} else {
76-
// decide which behavior to eomploy when validator has not matched
77-
if(state.isComplexValidator()) {
78-
// this was a complex validator (ex oneOf) and the node has not been matched
79-
state.setMatchedNode(false);
80-
return Collections.unmodifiableSet(new LinkedHashSet<ValidationMessage>());
81-
}
82-
83-
// check whether the node which has not matched was mandatory or not
84-
if(getParentSchema().hasRequiredValidator())
85-
errors.addAll(getParentSchema().getRequiredValidator().validate(node, rootNode, at));
76+
// check whether the node which has not matched was mandatory or not
77+
if (getParentSchema().hasRequiredValidator()) {
78+
Set<ValidationMessage> requiredErrors = getParentSchema().getRequiredValidator().validate(node, rootNode, at);
79+
80+
if(!requiredErrors.isEmpty()) {
81+
// the node was mandatory, decide which behavior to employ when validator has not matched
82+
if (state.isComplexValidator()) {
83+
// this was a complex validator (ex oneOf) and the node has not been matched
84+
state.setMatchedNode(false);
85+
return Collections.unmodifiableSet(new LinkedHashSet<ValidationMessage>());
86+
} else {
87+
errors.addAll(requiredErrors);
88+
}
89+
}
90+
}
8691
}
8792
}
8893

src/test/resources/draft2019-09/oneOf.json

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,5 +202,47 @@
202202
"valid": false
203203
}
204204
]
205+
},
206+
{
207+
"description": "oneOf with missing optional property",
208+
"schema": {
209+
"oneOf": [
210+
{
211+
"properties": {
212+
"bar": true,
213+
"baz": true
214+
},
215+
"required": ["bar"]
216+
},
217+
{
218+
"properties": {
219+
"foo": true
220+
},
221+
"required": ["foo"]
222+
}
223+
]
224+
},
225+
"tests": [
226+
{
227+
"description": "first oneOf valid",
228+
"data": {"bar": 8},
229+
"valid": true
230+
},
231+
{
232+
"description": "second oneOf valid",
233+
"data": {"foo": "foo"},
234+
"valid": true
235+
},
236+
{
237+
"description": "both oneOf valid",
238+
"data": {"foo": "foo", "bar": 8},
239+
"valid": false
240+
},
241+
{
242+
"description": "neither oneOf valid",
243+
"data": {"baz": "quux"},
244+
"valid": false
245+
}
246+
]
205247
}
206248
]

src/test/resources/draft4/oneOf.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,9 @@
128128
"oneOf": [
129129
{
130130
"type": "object",
131+
"required": [
132+
"id"
133+
],
131134
"properties": {
132135
"color": {
133136
"type": "string"
@@ -175,6 +178,13 @@
175178
"type": "INVALID_TYPE"
176179
},
177180
"valid": false
181+
},
182+
{
183+
"description": "first oneOf missing property but still valid",
184+
"data": {
185+
"id": "abc"
186+
},
187+
"valid": true
178188
}
179189
]
180190
},

src/test/resources/draft6/oneOf.json

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,5 +202,47 @@
202202
"valid": false
203203
}
204204
]
205+
},
206+
{
207+
"description": "oneOf with missing optional property",
208+
"schema": {
209+
"oneOf": [
210+
{
211+
"properties": {
212+
"bar": true,
213+
"baz": true
214+
},
215+
"required": ["bar"]
216+
},
217+
{
218+
"properties": {
219+
"foo": true
220+
},
221+
"required": ["foo"]
222+
}
223+
]
224+
},
225+
"tests": [
226+
{
227+
"description": "first oneOf valid",
228+
"data": {"bar": 8},
229+
"valid": true
230+
},
231+
{
232+
"description": "second oneOf valid",
233+
"data": {"foo": "foo"},
234+
"valid": true
235+
},
236+
{
237+
"description": "both oneOf valid",
238+
"data": {"foo": "foo", "bar": 8},
239+
"valid": false
240+
},
241+
{
242+
"description": "neither oneOf valid",
243+
"data": {"baz": "quux"},
244+
"valid": false
245+
}
246+
]
205247
}
206248
]

src/test/resources/draft7/oneOf.json

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,5 +202,47 @@
202202
"valid": false
203203
}
204204
]
205+
},
206+
{
207+
"description": "oneOf with missing optional property",
208+
"schema": {
209+
"oneOf": [
210+
{
211+
"properties": {
212+
"bar": true,
213+
"baz": true
214+
},
215+
"required": ["bar"]
216+
},
217+
{
218+
"properties": {
219+
"foo": true
220+
},
221+
"required": ["foo"]
222+
}
223+
]
224+
},
225+
"tests": [
226+
{
227+
"description": "first oneOf valid",
228+
"data": {"bar": 8},
229+
"valid": true
230+
},
231+
{
232+
"description": "second oneOf valid",
233+
"data": {"foo": "foo"},
234+
"valid": true
235+
},
236+
{
237+
"description": "both oneOf valid",
238+
"data": {"foo": "foo", "bar": 8},
239+
"valid": false
240+
},
241+
{
242+
"description": "neither oneOf valid",
243+
"data": {"baz": "quux"},
244+
"valid": false
245+
}
246+
]
205247
}
206248
]

0 commit comments

Comments
 (0)