Skip to content

Commit 9cb204b

Browse files
authored
Remove additional properties validation message when there are other … (#473)
* Remove additional properties validation message when there are other types of message in OneOfValidator * Add unit tests
1 parent 9c2311c commit 9cb204b

File tree

9 files changed

+182
-0
lines changed

9 files changed

+182
-0
lines changed

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

+9
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import org.slf4j.LoggerFactory;
2222

2323
import java.util.*;
24+
import java.util.stream.Collectors;
2425

2526
public class OneOfValidator extends BaseJsonValidator implements JsonValidator {
2627
private static final Logger logger = LoggerFactory.getLogger(OneOfValidator.class);
@@ -184,6 +185,14 @@ public Set<ValidationMessage> validate(JsonNode node, JsonNode rootNode, String
184185
// ensure there is always an "OneOf" error reported if number of valid schemas is not equal to 1.
185186
else if (numberOfValidSchema < 1) {
186187
if (!childErrors.isEmpty()) {
188+
if (childErrors.size() > 1) {
189+
Set<ValidationMessage> notAdditionalPropertiesOnly = childErrors.stream()
190+
.filter((ValidationMessage validationMessage) -> !ValidatorTypeCode.ADDITIONAL_PROPERTIES.getValue().equals(validationMessage.getType()))
191+
.collect(Collectors.toSet());
192+
if (notAdditionalPropertiesOnly.size() > 0) {
193+
childErrors = notAdditionalPropertiesOnly;
194+
}
195+
}
187196
errors.addAll(childErrors);
188197
}
189198
if( failFast ){
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package com.networknt.schema;
2+
3+
import com.fasterxml.jackson.databind.JsonNode;
4+
import com.fasterxml.jackson.databind.ObjectMapper;
5+
import org.junit.jupiter.api.Assertions;
6+
import org.junit.jupiter.api.BeforeAll;
7+
import org.junit.jupiter.api.DisplayName;
8+
import org.junit.jupiter.api.Test;
9+
10+
import java.io.InputStream;
11+
import java.util.Set;
12+
13+
public class Issue470Test {
14+
15+
private static JsonSchema schema;
16+
17+
@BeforeAll
18+
static void init() {
19+
JsonSchemaFactory factory = JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V7);
20+
String schemaPath = "/schema/issue470-v7.json";
21+
InputStream schemaInputStream = Issue470Test.class.getResourceAsStream(schemaPath);
22+
schema = factory.getSchema(schemaInputStream);
23+
}
24+
25+
private JsonNode getJsonNodeFromJsonData(String jsonFilePath) throws Exception {
26+
InputStream content = getClass().getResourceAsStream(jsonFilePath);
27+
ObjectMapper mapper = new ObjectMapper();
28+
return mapper.readTree(content);
29+
}
30+
31+
@Test
32+
@DisplayName("Test valid oneOf option 1")
33+
public void testValidJson1() throws Exception {
34+
JsonNode node = getJsonNodeFromJsonData("/data/issue470-valid-1.json");
35+
Set<ValidationMessage> errors = schema.validate(node);
36+
Assertions.assertTrue(errors.isEmpty());
37+
}
38+
39+
@Test
40+
@DisplayName("Test valid oneOf option 2")
41+
public void testValidJson2() throws Exception {
42+
JsonNode node = getJsonNodeFromJsonData("/data/issue470-valid-2.json");
43+
Set<ValidationMessage> errors = schema.validate(node);
44+
Assertions.assertTrue(errors.isEmpty());
45+
}
46+
47+
@Test
48+
@DisplayName("Test invalid oneOf option 1 - wrong type")
49+
public void testInvalidJson1() throws Exception {
50+
JsonNode node = getJsonNodeFromJsonData("/data/issue470-invalid-1.json");
51+
Set<ValidationMessage> errors = schema.validate(node);
52+
Assertions.assertEquals(1, errors.size());
53+
Assertions.assertEquals("$.search.byName.name: integer found, string expected", errors.iterator().next().getMessage());
54+
}
55+
56+
@Test
57+
@DisplayName("Test invalid oneOf option 1 - invalid value")
58+
public void testInvalidJson2() throws Exception {
59+
JsonNode node = getJsonNodeFromJsonData("/data/issue470-invalid-2.json");
60+
Set<ValidationMessage> errors = schema.validate(node);
61+
Assertions.assertEquals(1, errors.size());
62+
Assertions.assertEquals("$.search.byName.name: may only be 20 characters long", errors.iterator().next().getMessage());
63+
}
64+
65+
@Test
66+
@DisplayName("Test invalid oneOf option 2 - wrong type")
67+
public void testInvalidJson3() throws Exception {
68+
JsonNode node = getJsonNodeFromJsonData("/data/issue470-invalid-3.json");
69+
Set<ValidationMessage> errors = schema.validate(node);
70+
Assertions.assertEquals(1, errors.size());
71+
Assertions.assertEquals("$.search.byAge.age: string found, integer expected", errors.iterator().next().getMessage());
72+
}
73+
74+
@Test
75+
@DisplayName("Test invalid oneOf option 2 - invalid value")
76+
public void testInvalidJson4() throws Exception {
77+
JsonNode node = getJsonNodeFromJsonData("/data/issue470-invalid-4.json");
78+
Set<ValidationMessage> errors = schema.validate(node);
79+
Assertions.assertEquals(1, errors.size());
80+
Assertions.assertEquals("$.search.byAge.age: must have a maximum value of 150", errors.iterator().next().getMessage());
81+
}
82+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"search": {
3+
"byName": {
4+
"name": 123
5+
}
6+
}
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"search": {
3+
"byName": {
4+
"name": "Too loooooooooong name"
5+
}
6+
}
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"search": {
3+
"byAge": {
4+
"age": "20"
5+
}
6+
}
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"search": {
3+
"byAge": {
4+
"age": 200
5+
}
6+
}
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"search": {
3+
"byName": {
4+
"name": "John"
5+
}
6+
}
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"search": {
3+
"byAge": {
4+
"age": 35
5+
}
6+
}
7+
}
+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-07/schema#",
3+
"$id": "https://example.com/issue-470.json",
4+
"title": "OneOf validation message",
5+
"description": "Test description",
6+
"type": "object",
7+
"properties": {
8+
"search": {
9+
"type": "object",
10+
"oneOf": [
11+
{
12+
"type": "object",
13+
"properties": {
14+
"byName": {
15+
"type": "object",
16+
"properties": {
17+
"name": {
18+
"type": "string",
19+
"maxLength": 20,
20+
"minLength": 1
21+
}
22+
},
23+
"additionalProperties": false
24+
}
25+
},
26+
"additionalProperties": false
27+
},
28+
{
29+
"type": "object",
30+
"properties": {
31+
"byAge": {
32+
"type": "object",
33+
"properties": {
34+
"age": {
35+
"type": "integer",
36+
"maximum": 150,
37+
"minimum": 1
38+
}
39+
},
40+
"additionalProperties": false
41+
}
42+
},
43+
"additionalProperties": false
44+
}
45+
]
46+
}
47+
},
48+
"additionalProperties": false
49+
}

0 commit comments

Comments
 (0)