Repository: networknt/json-schema-validator
Pull request #559 (2022-04-24 21:30:12)

proposal for issue #535, part 2: fix the same issue in AnyOfValidator, too
As stated in https://github.com/networknt/json-schema-validator/issues/535, the same issue with receiving superfluous validation messages of type "required" after at least one subschema has validated without error does also apply to AnyOfValidator.

Here's my proposed fix for this second part... 😄 

@RenegadeWizard and @stevehu : please validate - many thanks! 👍 

AndreasALoew: Please note that the **current snapshot of master has some test failures** - but they are NOT due to this my PR:

```
[ERROR] Errors:
[ERROR]   V201909JsonSchemaTest.testRefRemoteValidator:315->BaseSuiteJsonSchemaTest.runTestFile:163 » IllegalState
[ERROR]   V4JsonSchemaTest.testIdSchemaWithUrl:287->BaseSuiteJsonSchemaTest.runTestFile:163 » IllegalState
[ERROR]   V4JsonSchemaTest.testLoadingWithId:38 » FileNotFound http://localhost:1234/sel...
[ERROR]   V4JsonSchemaTest.testRefRemoteValidator:247->BaseSuiteJsonSchemaTest.runTestFile:163 » IllegalState
[ERROR]   V6JsonSchemaTest.testRefRemoteValidator:212->BaseSuiteJsonSchemaTest.runTestFile:163 » IllegalState
[ERROR]   V7JsonSchemaTest.testRefRemoteValidator:308->BaseSuiteJsonSchemaTest.runTestFile:163 » IllegalState
[INFO]
[ERROR] Tests run: 374, Failures: 0, Errors: 6, Skipped: 56
```

Patch:
diff --git a/pom.xml b/pom.xml
index 5492433..1931f40 100644
--- a/pom.xml
+++ b/pom.xml
@@ -20,7 +20,7 @@
     <modelVersion>4.0.0</modelVersion>
     <groupId>com.networknt</groupId>
     <artifactId>json-schema-validator</artifactId>
-    <version>1.0.69</version>
+    <version>1.0.70-SNAPSHOT</version>
     <packaging>bundle</packaging>
     <description>A json schema validator that supports draft v4, v6, v7 and v2019-09</description>
     <url>https://github.com/networknt/json-schema-validator</url>
@@ -241,7 +241,7 @@
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-javadoc-plugin</artifactId>
-                <version>3.2.0</version>
+                <version>3.4.0</version>
                 <executions>
                     <execution>
                         <id>attach-javadocs</id>
@@ -282,6 +282,9 @@
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-surefire-plugin</artifactId>
                 <version>2.22.2</version>
+                <configuration>
+                    <argLine>-Duser.language=en -Duser.region=GB</argLine>
+                </configuration>
             </plugin>
             <!-- JACOCO added for code coverage -->
             <plugin>
diff --git a/src/main/java/com/networknt/schema/AnyOfValidator.java b/src/main/java/com/networknt/schema/AnyOfValidator.java
index 66ebd5c..461580e 100644
--- a/src/main/java/com/networknt/schema/AnyOfValidator.java
+++ b/src/main/java/com/networknt/schema/AnyOfValidator.java
@@ -70,6 +70,7 @@ public class AnyOfValidator extends BaseJsonValidator implements JsonValidator {
         CollectorContext.getInstance().add(UnEvaluatedPropertiesValidator.EVALUATED_PROPERTIES, new ArrayList<>());
 
         try {
+            int numberOfValidSubSchemas = 0;
             for (JsonSchema schema : schemas) {
                 Set<ValidationMessage> errors = new HashSet<>();
                 if (schema.getValidators().containsKey(typeValidatorName)) {
@@ -86,6 +87,17 @@ public class AnyOfValidator extends BaseJsonValidator implements JsonValidator {
                 } else {
                     errors = schema.walk(node, rootNode, at, true);
                 }
+                
+                // check if any validation errors have occurred
+                if (errors.isEmpty()) {
+                    // check whether there are no errors HOWEVER we have validated the exact validator
+                    if (!state.hasMatchedNode()) {
+                        continue;
+                    }
+                    // we found a valid subschema, so increase counter
+                    numberOfValidSubSchemas++;
+                }                
+                
                 if (errors.isEmpty() && (!this.validationContext.getConfig().isOpenAPI3StyleDiscriminators())) {
                     // Clear all errors.
                     allErrors.clear();
@@ -106,6 +118,14 @@ public class AnyOfValidator extends BaseJsonValidator implements JsonValidator {
                 allErrors.addAll(errors);
             }
 
+            // determine only those errors which are NOT of type "required" property missing
+            Set<ValidationMessage> childNotRequiredErrors = allErrors.stream().filter(error -> !ValidatorTypeCode.REQUIRED.getValue().equals(error.getType())).collect(Collectors.toSet());
+
+            // in case we had at least one (anyOf, i.e. any number >= 1 of) valid subschemas, we can remove all other errors about "required" properties
+            if (numberOfValidSubSchemas >= 1 && childNotRequiredErrors.isEmpty()) {
+                allErrors = childNotRequiredErrors;
+            }
+
             if (this.validationContext.getConfig().isOpenAPI3StyleDiscriminators() && discriminatorContext.isActive()) {
                 final Set<ValidationMessage> errors = new HashSet<ValidationMessage>();
                 errors.add(buildValidationMessage(at, "based on the provided discriminator. No alternative could be chosen based on the discriminator property"));
diff --git a/src/main/java/com/networknt/schema/PropertiesValidator.java b/src/main/java/com/networknt/schema/PropertiesValidator.java
index f09e52e..14c0cff 100644
--- a/src/main/java/com/networknt/schema/PropertiesValidator.java
+++ b/src/main/java/com/networknt/schema/PropertiesValidator.java
@@ -17,6 +17,7 @@
 package com.networknt.schema;
 
 import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.JsonNodeType;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import com.networknt.schema.walk.DefaultPropertyWalkListenerRunner;
 import com.networknt.schema.walk.WalkListenerRunner;
@@ -114,7 +115,7 @@ public class PropertiesValidator extends BaseJsonValidator implements JsonValida
     @Override
     public Set<ValidationMessage> walk(JsonNode node, JsonNode rootNode, String at, boolean shouldValidateSchema) {
         HashSet<ValidationMessage> validationMessages = new LinkedHashSet<ValidationMessage>();
-        if (applyDefaultsStrategy.shouldApplyPropertyDefaults()) {
+        if (applyDefaultsStrategy.shouldApplyPropertyDefaults() && node.getNodeType() == JsonNodeType.OBJECT) {
             applyPropertyDefaults((ObjectNode) node);
         }
         if (shouldValidateSchema) {
diff --git a/src/main/java/com/networknt/schema/uri/URLFactory.java b/src/main/java/com/networknt/schema/uri/URLFactory.java
index 544707c..5850a3b 100644
--- a/src/main/java/com/networknt/schema/uri/URLFactory.java
+++ b/src/main/java/com/networknt/schema/uri/URLFactory.java
@@ -40,10 +40,8 @@ public final class URLFactory implements URIFactory {
     @Override
     public URI create(final String uri) {
         try {
-            return new URL(uri).toURI();
-        } catch (MalformedURLException e) {
-            throw new IllegalArgumentException("Unable to create URI.", e);
-        } catch (URISyntaxException e) {
+            return URI.create(uri);
+        } catch (IllegalArgumentException e) {
             throw new IllegalArgumentException("Unable to create URI.", e);
         }
     }
diff --git a/src/main/java/com/networknt/schema/utils/JsonNodeUtil.java b/src/main/java/com/networknt/schema/utils/JsonNodeUtil.java
index fb89556..9d18236 100644
--- a/src/main/java/com/networknt/schema/utils/JsonNodeUtil.java
+++ b/src/main/java/com/networknt/schema/utils/JsonNodeUtil.java
@@ -83,7 +83,6 @@ public class JsonNodeUtil {
                 return true;
             }
 
-            ValidatorState state = (ValidatorState) CollectorContext.getInstance().get(ValidatorState.VALIDATOR_STATE_KEY);
             if(JsonType.NULL.equals(nodeType)) {
                 if(parentSchema != null) {
                     if( parentSchema.getParentSchema() != null && JsonNodeUtil.isNodeNullable(parentSchema.getParentSchema().getSchemaNode(), config) || JsonNodeUtil.isNodeNullable(parentSchema.getSchemaNode()) ) {


Test patch:
diff --git a/src/test/java/com/networknt/schema/PropertiesValidatorTest.java b/src/test/java/com/networknt/schema/PropertiesValidatorTest.java
new file mode 100644
index 0000000..887f6ca
--- /dev/null
+++ b/src/test/java/com/networknt/schema/PropertiesValidatorTest.java
@@ -0,0 +1,30 @@
+package com.networknt.schema;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Created by josejulio on 25/04/22.
+ */
+public class PropertiesValidatorTest extends BaseJsonSchemaValidatorTest {
+
+    @Test
+    public void testDoesNotThrowWhenApplyingDefaultPropertiesToNonObjects() throws Exception {
+        Assertions.assertDoesNotThrow(() -> {
+            JsonSchemaFactory factory = JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V4);
+
+            SchemaValidatorsConfig schemaValidatorsConfig = new SchemaValidatorsConfig();
+            schemaValidatorsConfig.setApplyDefaultsStrategy(new ApplyDefaultsStrategy(
+                    true,
+                    true,
+                    true
+            ));
+
+            JsonSchema schema = factory.getSchema("{\"type\":\"object\",\"properties\":{\"foo\":{\"type\":\"object\", \"properties\": {} },\"i-have-default\":{\"type\":\"string\",\"default\":\"foo\"}}}", schemaValidatorsConfig);
+            JsonNode node = getJsonNodeFromStringContent("{\"foo\": \"bar\"}");
+            ValidationResult result = schema.walk(node, true);
+            Assertions.assertEquals(result.getValidationMessages().size(), 1);
+        });
+    }
+}