Skip to content

Fix enum validator messages for object, array and text nodes #1095

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion src/main/java/com/networknt/schema/EnumValidator.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ public class EnumValidator extends BaseJsonValidator implements JsonValidator {
private final Set<JsonNode> nodes;
private final String error;

static String asText(JsonNode node) {
if (node.isObject() || node.isArray() || node.isTextual()) {
// toString for isTextual is so that there are quotes
return node.toString();
}
return node.asText();
}

public EnumValidator(SchemaLocation schemaLocation, JsonNodePath evaluationPath, JsonNode schemaNode, JsonSchema parentSchema, ValidationContext validationContext) {
super(schemaLocation, evaluationPath, schemaNode, parentSchema, ValidatorTypeCode.ENUM, validationContext);
if (schemaNode != null && schemaNode.isArray()) {
Expand All @@ -58,7 +66,7 @@ public EnumValidator(SchemaLocation schemaLocation, JsonNodePath evaluationPath,
}

sb.append(separator);
sb.append(n.asText());
sb.append(asText(n));
separator = ", ";
}

Expand Down
115 changes: 115 additions & 0 deletions src/test/java/com/networknt/schema/EnumValidatorTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/*
* Copyright (c) 2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.networknt.schema;

import static org.junit.jupiter.api.Assertions.*;

import java.util.List;
import java.util.stream.Collectors;

import org.junit.jupiter.api.Test;

import com.networknt.schema.SpecVersion.VersionFlag;

/**
* EnumValidator test.
*/
class EnumValidatorTest {

@Test
void enumWithObjectNodes() {
String schemaData = "{\r\n"
+ " \"title\": \"Severity\",\r\n"
+ " \"type\": \"object\",\r\n"
+ " \"properties\": {\r\n"
+ " \"name\": {\r\n"
+ " \"title\": \"Name\",\r\n"
+ " \"description\": \"The human readable name of the severity\",\r\n"
+ " \"type\": \"string\"\r\n"
+ " },\r\n"
+ " \"cardinality\": {\r\n"
+ " \"title\": \"Cardinality\",\r\n"
+ " \"description\": \"The severities cardinality, the higher the worse it gets\",\r\n"
+ " \"type\": \"integer\",\r\n"
+ " \"minimum\": 0,\r\n"
+ " \"maximum\": 50,\r\n"
+ " \"multipleOf\": 10\r\n"
+ " }\r\n"
+ " },\r\n"
+ " \"additionalProperties\": false,\r\n"
+ " \"required\": [\r\n"
+ " \"name\",\r\n"
+ " \"cardinality\"\r\n"
+ " ],\r\n"
+ " \"enum\": [\r\n"
+ " {\r\n"
+ " \"name\": \"EMPTY\",\r\n"
+ " \"cardinality\": 0\r\n"
+ " },\r\n"
+ " {\r\n"
+ " \"name\": \"OK\",\r\n"
+ " \"cardinality\": 20\r\n"
+ " },\r\n"
+ " {\r\n"
+ " \"name\": \"UNKNOWN\",\r\n"
+ " \"cardinality\": 30\r\n"
+ " },\r\n"
+ " {\r\n"
+ " \"name\": \"WARNING\",\r\n"
+ " \"cardinality\": 40\r\n"
+ " },\r\n"
+ " {\r\n"
+ " \"name\": \"CRITICAL\",\r\n"
+ " \"cardinality\": 50\r\n"
+ " }\r\n"
+ " ],\r\n"
+ " \"default\": {\r\n"
+ " \"name\": \"UNKNOWN\",\r\n"
+ " \"cardinality\": 30\r\n"
+ " }\r\n"
+ "}";
String inputData = "{\r\n"
+ " \"name\": \"FOO\",\r\n"
+ " \"cardinality\": 50\r\n"
+ "}";
JsonSchema schema = JsonSchemaFactory.getInstance(VersionFlag.V202012).getSchema(schemaData,
SchemaValidatorsConfig.builder().build());
List<ValidationMessage> messages = schema.validate(inputData, InputFormat.JSON).stream().collect(Collectors.toList());
assertEquals(1, messages.size());
ValidationMessage message = messages.get(0);
assertEquals(
": 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}]",
message.toString());
}

@Test
void enumWithHeterogenousNodes() {
String schemaData = "{\r\n"
+ " \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\r\n"
+ " \"enum\": [6, \"foo\", [], true, {\"foo\": 12}]\r\n"
+ " }";
String inputData = "{\r\n"
+ " \"name\": \"FOO\",\r\n"
+ " \"cardinality\": 50\r\n"
+ "}";
JsonSchema schema = JsonSchemaFactory.getInstance(VersionFlag.V202012).getSchema(schemaData,
SchemaValidatorsConfig.builder().build());
List<ValidationMessage> messages = schema.validate(inputData, InputFormat.JSON).stream().collect(Collectors.toList());
assertEquals(1, messages.size());
ValidationMessage message = messages.get(0);
assertEquals(": does not have a value in the enumeration [6, \"foo\", [], true, {\"foo\":12}]", message.toString());
}
}
2 changes: 1 addition & 1 deletion src/test/java/com/networknt/schema/Issue342Test.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,6 @@ public void propertyNameEnumShouldFailV7() throws Exception {
Assertions.assertEquals(1, errors.size());
final ValidationMessage error = errors.iterator().next();
Assertions.assertEquals("$", error.getInstanceLocation().toString());
Assertions.assertEquals("$: property 'z' name is not valid: does not have a value in the enumeration [a, b, c]", error.getMessage());
Assertions.assertEquals("$: property 'z' name is not valid: does not have a value in the enumeration [\"a\", \"b\", \"c\"]", error.getMessage());
}
}
2 changes: 1 addition & 1 deletion src/test/java/com/networknt/schema/Issue662Test.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ void testCorrectErrorForInvalidValue() throws IOException {
assertTrue(errorMessages
.contains("$.properties.optionalObject.anyOf[0].type = $.optionalObject: object found, null expected"));
assertTrue(errorMessages.contains(
"$.properties.optionalObject.anyOf[1].properties.value.enum = $.optionalObject.value: does not have a value in the enumeration [one, two]"));
"$.properties.optionalObject.anyOf[1].properties.value.enum = $.optionalObject.value: does not have a value in the enumeration [\"one\", \"two\"]"));
}

private static String resource(String name) {
Expand Down
2 changes: 1 addition & 1 deletion src/test/java/com/networknt/schema/Issue898Test.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ void testMessagesWithSingleQuotes() throws Exception {
.collect(toList());

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

Expand Down
2 changes: 1 addition & 1 deletion src/test/java/com/networknt/schema/OutputFormatTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ void customFormat() {
+ " \"id\": 1\n"
+ "}";
List<ValidationMessage> messages = schema.validate(inputData, InputFormat.JSON, DETAILED).stream().collect(Collectors.toList());
assertEquals("[/type] with value 'cat' does not have a value in the enumeration [book, author]", messages.get(0).getMessage());
assertEquals("[/type] with value 'cat' does not have a value in the enumeration [\"book\", \"author\"]", messages.get(0).getMessage());
assertEquals("[/id] with value '1' integer found, string expected", messages.get(1).getMessage());
}
}