diff --git a/src/main/java/com/networknt/schema/AllOfValidator.java b/src/main/java/com/networknt/schema/AllOfValidator.java index 967dc440..c456f18f 100644 --- a/src/main/java/com/networknt/schema/AllOfValidator.java +++ b/src/main/java/com/networknt/schema/AllOfValidator.java @@ -112,7 +112,7 @@ protected Set validate(ExecutionContext executionContext, Jso @Override public Set walk(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, JsonNodePath instanceLocation, boolean shouldValidateSchema) { - if (shouldValidateSchema) { + if (shouldValidateSchema && node != null) { return validate(executionContext, node, rootNode, instanceLocation, true); } for (JsonSchema schema : this.schemas) { diff --git a/src/main/java/com/networknt/schema/AnyOfValidator.java b/src/main/java/com/networknt/schema/AnyOfValidator.java index 02440f12..8dd18d4e 100644 --- a/src/main/java/com/networknt/schema/AnyOfValidator.java +++ b/src/main/java/com/networknt/schema/AnyOfValidator.java @@ -162,13 +162,13 @@ && canShortCircuit() && canShortCircuit(executionContext)) { @Override public Set walk(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, JsonNodePath instanceLocation, boolean shouldValidateSchema) { - if (shouldValidateSchema) { + if (shouldValidateSchema && node != null) { return validate(executionContext, node, rootNode, instanceLocation, true); } for (JsonSchema schema : this.schemas) { schema.walk(executionContext, node, rootNode, instanceLocation, false); } - return new LinkedHashSet<>(); + return Collections.emptySet(); } /** diff --git a/src/main/java/com/networknt/schema/NotValidator.java b/src/main/java/com/networknt/schema/NotValidator.java index e943a511..c63ae34a 100644 --- a/src/main/java/com/networknt/schema/NotValidator.java +++ b/src/main/java/com/networknt/schema/NotValidator.java @@ -68,18 +68,11 @@ protected Set validate(ExecutionContext executionContext, Jso @Override public Set walk(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, JsonNodePath instanceLocation, boolean shouldValidateSchema) { - if (shouldValidateSchema) { + if (shouldValidateSchema && node != null) { return validate(executionContext, node, rootNode, instanceLocation, true); } - Set errors = this.schema.walk(executionContext, node, rootNode, instanceLocation, shouldValidateSchema); - if (errors.isEmpty()) { - return Collections.singleton(message().instanceNode(node).instanceLocation(instanceLocation) - .locale(executionContext.getExecutionConfig().getLocale()) - .failFast(executionContext.isFailFast()).arguments(this.schema.toString()) - .build()); - } - return Collections.emptySet(); + return this.schema.walk(executionContext, node, rootNode, instanceLocation, false); } @Override diff --git a/src/main/java/com/networknt/schema/OneOfValidator.java b/src/main/java/com/networknt/schema/OneOfValidator.java index 1807305b..caca8435 100644 --- a/src/main/java/com/networknt/schema/OneOfValidator.java +++ b/src/main/java/com/networknt/schema/OneOfValidator.java @@ -230,11 +230,11 @@ protected boolean canShortCircuit() { @Override public Set walk(ExecutionContext executionContext, JsonNode node, JsonNode rootNode, JsonNodePath instanceLocation, boolean shouldValidateSchema) { HashSet validationMessages = new LinkedHashSet<>(); - if (shouldValidateSchema) { + if (shouldValidateSchema && node != null) { validationMessages.addAll(validate(executionContext, node, rootNode, instanceLocation, true)); } else { for (JsonSchema schema : this.schemas) { - schema.walk(executionContext, node, rootNode, instanceLocation, shouldValidateSchema); + schema.walk(executionContext, node, rootNode, instanceLocation, false); } } return validationMessages; diff --git a/src/test/java/com/networknt/schema/AllOfValidatorTest.java b/src/test/java/com/networknt/schema/AllOfValidatorTest.java index c56066e3..0b5597f9 100644 --- a/src/test/java/com/networknt/schema/AllOfValidatorTest.java +++ b/src/test/java/com/networknt/schema/AllOfValidatorTest.java @@ -37,4 +37,31 @@ void invalidTypeShouldThrowJsonSchemaException() { JsonSchemaException ex = assertThrows(JsonSchemaException.class, () -> factory.getSchema(schemaData)); assertEquals("type", ex.getValidationMessage().getMessageKey()); } + + @Test + void walkValidationWithNullNodeShouldNotValidate() { + String schemaContents = " {\r\n" + + " \"type\": \"object\",\r\n" + + " \"properties\": {\r\n" + + " \"prop1\": {\r\n" + + " \"allOf\": [\r\n" + + " {\r\n" + + " \"type\": \"string\"\r\n" + + " },\r\n" + + " {\r\n" + + " \"type\": \"integer\"\r\n" + + " }\r\n" + + " ]\r\n" + + " }\r\n" + + " },\r\n" + + " \"additionalProperties\": false\r\n" + + " }"; + + String jsonContents = "{}"; + + JsonSchemaFactory factory = JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V7); + JsonSchema schema = factory.getSchema(schemaContents); + ValidationResult result = schema.walk(jsonContents, InputFormat.JSON, true); + assertEquals(true, result.getValidationMessages().isEmpty()); + } } diff --git a/src/test/java/com/networknt/schema/AnyOfValidatorTest.java b/src/test/java/com/networknt/schema/AnyOfValidatorTest.java index ffbb6833..d6914ff1 100644 --- a/src/test/java/com/networknt/schema/AnyOfValidatorTest.java +++ b/src/test/java/com/networknt/schema/AnyOfValidatorTest.java @@ -37,4 +37,31 @@ void invalidTypeShouldThrowJsonSchemaException() { JsonSchemaException ex = assertThrows(JsonSchemaException.class, () -> factory.getSchema(schemaData)); assertEquals("type", ex.getValidationMessage().getMessageKey()); } + + @Test + void walkValidationWithNullNodeShouldNotValidate() { + String schemaContents = " {\r\n" + + " \"type\": \"object\",\r\n" + + " \"properties\": {\r\n" + + " \"prop1\": {\r\n" + + " \"anyOf\": [\r\n" + + " {\r\n" + + " \"type\": \"string\"\r\n" + + " },\r\n" + + " {\r\n" + + " \"type\": \"integer\"\r\n" + + " }\r\n" + + " ]\r\n" + + " }\r\n" + + " },\r\n" + + " \"additionalProperties\": false\r\n" + + " }"; + + String jsonContents = "{}"; + + JsonSchemaFactory factory = JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V7); + JsonSchema schema = factory.getSchema(schemaContents); + ValidationResult result = schema.walk(jsonContents, InputFormat.JSON, true); + assertEquals(true, result.getValidationMessages().isEmpty()); + } } diff --git a/src/test/java/com/networknt/schema/NotValidatorTest.java b/src/test/java/com/networknt/schema/NotValidatorTest.java new file mode 100644 index 00000000..50607fe2 --- /dev/null +++ b/src/test/java/com/networknt/schema/NotValidatorTest.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2025 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.assertEquals; + +import org.junit.jupiter.api.Test; + +class NotValidatorTest { + @Test + void walkValidationWithNullNodeShouldNotValidate() { + String schemaContents = "{\r\n" + + " \"type\": \"object\",\r\n" + + " \"properties\": {\r\n" + + " \"prop1\": {\r\n" + + " \"not\": {\r\n" + + " \"type\": \"string\"\r\n" + + " }\r\n" + + " }\r\n" + + " },\r\n" + + " \"additionalProperties\": false\r\n" + + "}"; + + String jsonContents = "{}"; + + JsonSchemaFactory factory = JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V7); + JsonSchema schema = factory.getSchema(schemaContents); + ValidationResult result = schema.walk(jsonContents, InputFormat.JSON, true); + assertEquals(true, result.getValidationMessages().isEmpty()); + } +} diff --git a/src/test/java/com/networknt/schema/OneOfValidatorTest.java b/src/test/java/com/networknt/schema/OneOfValidatorTest.java index 6800595c..1df5bd46 100644 --- a/src/test/java/com/networknt/schema/OneOfValidatorTest.java +++ b/src/test/java/com/networknt/schema/OneOfValidatorTest.java @@ -469,4 +469,32 @@ void oneOfDiscriminatorEnabledWithDiscriminatorInSubclass() { assertEquals(3, messages3.size()); } + @Test + void walkValidationWithNullNodeShouldNotValidate() { + String schemaContents = " {\r\n" + + " \"type\": \"object\",\r\n" + + " \"properties\": {\r\n" + + " \"prop1\": {\r\n" + + " \"oneOf\": [\r\n" + + " {\r\n" + + " \"type\": \"string\"\r\n" + + " },\r\n" + + " {\r\n" + + " \"type\": \"integer\"\r\n" + + " }\r\n" + + " ]\r\n" + + " }\r\n" + + " },\r\n" + + " \"additionalProperties\": false\r\n" + + " }"; + + String jsonContents = "{}"; + + JsonSchemaFactory factory = JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V7); + JsonSchema schema = factory.getSchema(schemaContents); + ValidationResult result = schema.walk(jsonContents, InputFormat.JSON, true); + result.getValidationMessages().forEach(m -> System.out.println(m)); + assertEquals(true, result.getValidationMessages().isEmpty()); + } + }