Skip to content

Commit b160c11

Browse files
authored
Fix enum validator messages for object, array and text nodes (#1095)
1 parent a9e8a49 commit b160c11

File tree

6 files changed

+128
-5
lines changed

6 files changed

+128
-5
lines changed

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,14 @@ public class EnumValidator extends BaseJsonValidator implements JsonValidator {
3737
private final Set<JsonNode> nodes;
3838
private final String error;
3939

40+
static String asText(JsonNode node) {
41+
if (node.isObject() || node.isArray() || node.isTextual()) {
42+
// toString for isTextual is so that there are quotes
43+
return node.toString();
44+
}
45+
return node.asText();
46+
}
47+
4048
public EnumValidator(SchemaLocation schemaLocation, JsonNodePath evaluationPath, JsonNode schemaNode, JsonSchema parentSchema, ValidationContext validationContext) {
4149
super(schemaLocation, evaluationPath, schemaNode, parentSchema, ValidatorTypeCode.ENUM, validationContext);
4250
if (schemaNode != null && schemaNode.isArray()) {
@@ -58,7 +66,7 @@ public EnumValidator(SchemaLocation schemaLocation, JsonNodePath evaluationPath,
5866
}
5967

6068
sb.append(separator);
61-
sb.append(n.asText());
69+
sb.append(asText(n));
6270
separator = ", ";
6371
}
6472

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
/*
2+
* Copyright (c) 2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.networknt.schema;
17+
18+
import static org.junit.jupiter.api.Assertions.*;
19+
20+
import java.util.List;
21+
import java.util.stream.Collectors;
22+
23+
import org.junit.jupiter.api.Test;
24+
25+
import com.networknt.schema.SpecVersion.VersionFlag;
26+
27+
/**
28+
* EnumValidator test.
29+
*/
30+
class EnumValidatorTest {
31+
32+
@Test
33+
void enumWithObjectNodes() {
34+
String schemaData = "{\r\n"
35+
+ " \"title\": \"Severity\",\r\n"
36+
+ " \"type\": \"object\",\r\n"
37+
+ " \"properties\": {\r\n"
38+
+ " \"name\": {\r\n"
39+
+ " \"title\": \"Name\",\r\n"
40+
+ " \"description\": \"The human readable name of the severity\",\r\n"
41+
+ " \"type\": \"string\"\r\n"
42+
+ " },\r\n"
43+
+ " \"cardinality\": {\r\n"
44+
+ " \"title\": \"Cardinality\",\r\n"
45+
+ " \"description\": \"The severities cardinality, the higher the worse it gets\",\r\n"
46+
+ " \"type\": \"integer\",\r\n"
47+
+ " \"minimum\": 0,\r\n"
48+
+ " \"maximum\": 50,\r\n"
49+
+ " \"multipleOf\": 10\r\n"
50+
+ " }\r\n"
51+
+ " },\r\n"
52+
+ " \"additionalProperties\": false,\r\n"
53+
+ " \"required\": [\r\n"
54+
+ " \"name\",\r\n"
55+
+ " \"cardinality\"\r\n"
56+
+ " ],\r\n"
57+
+ " \"enum\": [\r\n"
58+
+ " {\r\n"
59+
+ " \"name\": \"EMPTY\",\r\n"
60+
+ " \"cardinality\": 0\r\n"
61+
+ " },\r\n"
62+
+ " {\r\n"
63+
+ " \"name\": \"OK\",\r\n"
64+
+ " \"cardinality\": 20\r\n"
65+
+ " },\r\n"
66+
+ " {\r\n"
67+
+ " \"name\": \"UNKNOWN\",\r\n"
68+
+ " \"cardinality\": 30\r\n"
69+
+ " },\r\n"
70+
+ " {\r\n"
71+
+ " \"name\": \"WARNING\",\r\n"
72+
+ " \"cardinality\": 40\r\n"
73+
+ " },\r\n"
74+
+ " {\r\n"
75+
+ " \"name\": \"CRITICAL\",\r\n"
76+
+ " \"cardinality\": 50\r\n"
77+
+ " }\r\n"
78+
+ " ],\r\n"
79+
+ " \"default\": {\r\n"
80+
+ " \"name\": \"UNKNOWN\",\r\n"
81+
+ " \"cardinality\": 30\r\n"
82+
+ " }\r\n"
83+
+ "}";
84+
String inputData = "{\r\n"
85+
+ " \"name\": \"FOO\",\r\n"
86+
+ " \"cardinality\": 50\r\n"
87+
+ "}";
88+
JsonSchema schema = JsonSchemaFactory.getInstance(VersionFlag.V202012).getSchema(schemaData,
89+
SchemaValidatorsConfig.builder().build());
90+
List<ValidationMessage> messages = schema.validate(inputData, InputFormat.JSON).stream().collect(Collectors.toList());
91+
assertEquals(1, messages.size());
92+
ValidationMessage message = messages.get(0);
93+
assertEquals(
94+
": does not have a value in the enumeration [{\"name\":\"EMPTY\",\"cardinality\":0}, {\"name\":\"OK\",\"cardinality\":20}, {\"name\":\"UNKNOWN\",\"cardinality\":30}, {\"name\":\"WARNING\",\"cardinality\":40}, {\"name\":\"CRITICAL\",\"cardinality\":50}]",
95+
message.toString());
96+
}
97+
98+
@Test
99+
void enumWithHeterogenousNodes() {
100+
String schemaData = "{\r\n"
101+
+ " \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\r\n"
102+
+ " \"enum\": [6, \"foo\", [], true, {\"foo\": 12}]\r\n"
103+
+ " }";
104+
String inputData = "{\r\n"
105+
+ " \"name\": \"FOO\",\r\n"
106+
+ " \"cardinality\": 50\r\n"
107+
+ "}";
108+
JsonSchema schema = JsonSchemaFactory.getInstance(VersionFlag.V202012).getSchema(schemaData,
109+
SchemaValidatorsConfig.builder().build());
110+
List<ValidationMessage> messages = schema.validate(inputData, InputFormat.JSON).stream().collect(Collectors.toList());
111+
assertEquals(1, messages.size());
112+
ValidationMessage message = messages.get(0);
113+
assertEquals(": does not have a value in the enumeration [6, \"foo\", [], true, {\"foo\":12}]", message.toString());
114+
}
115+
}

src/test/java/com/networknt/schema/Issue342Test.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,6 @@ public void propertyNameEnumShouldFailV7() throws Exception {
3333
Assertions.assertEquals(1, errors.size());
3434
final ValidationMessage error = errors.iterator().next();
3535
Assertions.assertEquals("$", error.getInstanceLocation().toString());
36-
Assertions.assertEquals("$: property 'z' name is not valid: does not have a value in the enumeration [a, b, c]", error.getMessage());
36+
Assertions.assertEquals("$: property 'z' name is not valid: does not have a value in the enumeration [\"a\", \"b\", \"c\"]", error.getMessage());
3737
}
3838
}

src/test/java/com/networknt/schema/Issue662Test.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ void testCorrectErrorForInvalidValue() throws IOException {
5151
assertTrue(errorMessages
5252
.contains("$.properties.optionalObject.anyOf[0].type = $.optionalObject: object found, null expected"));
5353
assertTrue(errorMessages.contains(
54-
"$.properties.optionalObject.anyOf[1].properties.value.enum = $.optionalObject.value: does not have a value in the enumeration [one, two]"));
54+
"$.properties.optionalObject.anyOf[1].properties.value.enum = $.optionalObject.value: does not have a value in the enumeration [\"one\", \"two\"]"));
5555
}
5656

5757
private static String resource(String name) {

src/test/java/com/networknt/schema/Issue898Test.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ void testMessagesWithSingleQuotes() throws Exception {
2323
.collect(toList());
2424

2525
Assertions.assertEquals(2, messages.size());
26-
Assertions.assertEquals("/foo: n'a pas de valeur dans l'énumération [foo1, foo2]", messages.get(0));
26+
Assertions.assertEquals("/foo: n'a pas de valeur dans l'énumération [\"foo1\", \"foo2\"]", messages.get(0));
2727
Assertions.assertEquals("/bar: ne correspond pas au modèle d'expression régulière (bar)+", messages.get(1));
2828
}
2929

src/test/java/com/networknt/schema/OutputFormatTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ void customFormat() {
114114
+ " \"id\": 1\n"
115115
+ "}";
116116
List<ValidationMessage> messages = schema.validate(inputData, InputFormat.JSON, DETAILED).stream().collect(Collectors.toList());
117-
assertEquals("[/type] with value 'cat' does not have a value in the enumeration [book, author]", messages.get(0).getMessage());
117+
assertEquals("[/type] with value 'cat' does not have a value in the enumeration [\"book\", \"author\"]", messages.get(0).getMessage());
118118
assertEquals("[/id] with value '1' integer found, string expected", messages.get(1).getMessage());
119119
}
120120
}

0 commit comments

Comments
 (0)