Repository: networknt/json-schema-validator
Pull request #543 (2022-03-30 08:20:24)

The bug fix for the issue 520
This is the bug fix for issue 520,the issue link is:
https://github.com/networknt/json-schema-validator/issues/520


Patch:
diff --git a/pom.xml b/pom.xml
index feaa95f..c98e805 100644
--- a/pom.xml
+++ b/pom.xml
@@ -72,6 +72,7 @@
         <version.hamcrest>2.2</version.hamcrest>
         <version.undertow>2.2.14.Final</version.undertow>
         <version.itu>1.5.1</version.itu>
+        <version.commons.io>2.11.0</version.commons.io>
     </properties>
     <dependencies>
         <dependency>
@@ -118,6 +119,12 @@
             <version>${version.junit}</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.13.2</version>
+            <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>org.mockito</groupId>
             <artifactId>mockito-core</artifactId>
@@ -136,6 +143,12 @@
             <version>${version.undertow}</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+            <version>${version.commons.io}</version>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
     <build>
         <sourceDirectory>${basedir}/src/main/java</sourceDirectory>
diff --git a/src/main/java/com/networknt/schema/AllOfValidator.java b/src/main/java/com/networknt/schema/AllOfValidator.java
index c84b56a..4a26180 100644
--- a/src/main/java/com/networknt/schema/AllOfValidator.java
+++ b/src/main/java/com/networknt/schema/AllOfValidator.java
@@ -22,6 +22,7 @@ import java.util.Iterator;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.node.ObjectNode;
@@ -49,7 +50,7 @@ public class AllOfValidator extends BaseJsonValidator implements JsonValidator {
     public Set<ValidationMessage> validate(JsonNode node, JsonNode rootNode, String at) {
         debug(logger, node, rootNode, at);
 
-        Set<ValidationMessage> errors = new LinkedHashSet<ValidationMessage>();
+        Set<ValidationMessage> childSchemaErrors = new LinkedHashSet<>();
 
         // As AllOf might contain multiple schemas take a backup of evaluatedProperties.
         Object backupEvaluatedProperties = CollectorContext.getInstance().get(UnEvaluatedPropertiesValidator.EVALUATED_PROPERTIES);
@@ -59,7 +60,7 @@ public class AllOfValidator extends BaseJsonValidator implements JsonValidator {
 
         for (JsonSchema schema : schemas) {
             try {
-                errors.addAll(schema.validate(node, rootNode, at));
+                childSchemaErrors.addAll(schema.validate(node, rootNode, at));
 
                 if (this.validationContext.getConfig().isOpenAPI3StyleDiscriminators()) {
                     final Iterator<JsonNode> arrayElements = schemaNode.elements();
@@ -93,7 +94,7 @@ public class AllOfValidator extends BaseJsonValidator implements JsonValidator {
                     }
                 }
             } finally {
-                if (errors.isEmpty()) {
+                if (childSchemaErrors.isEmpty()) {
                     List<String> backupEvaluatedPropertiesList = (backupEvaluatedProperties == null ? new ArrayList<>() : (List<String>) backupEvaluatedProperties);
                     backupEvaluatedPropertiesList.addAll((List<String>) CollectorContext.getInstance().get(UnEvaluatedPropertiesValidator.EVALUATED_PROPERTIES));
                     CollectorContext.getInstance().add(UnEvaluatedPropertiesValidator.EVALUATED_PROPERTIES, backupEvaluatedPropertiesList);
@@ -103,7 +104,13 @@ public class AllOfValidator extends BaseJsonValidator implements JsonValidator {
             }
         }
 
-        return Collections.unmodifiableSet(errors);
+        if(!childSchemaErrors.isEmpty()){
+            List<String> childSchemaErrorMessages = childSchemaErrors.stream().map(ValidationMessage::getMessage).collect(Collectors.toList());
+            String childMessages = String.join(", ", childSchemaErrorMessages);
+            return Collections.singleton(ValidationMessage.of(getValidatorType().getValue(), ValidatorTypeCode.ALL_OF, at, childMessages));
+        }
+
+        return Collections.unmodifiableSet(childSchemaErrors);
     }
 
     @Override
diff --git a/src/main/java/com/networknt/schema/AnyOfValidator.java b/src/main/java/com/networknt/schema/AnyOfValidator.java
index ae50409..309550e 100644
--- a/src/main/java/com/networknt/schema/AnyOfValidator.java
+++ b/src/main/java/com/networknt/schema/AnyOfValidator.java
@@ -113,6 +113,11 @@ public class AnyOfValidator extends BaseJsonValidator implements JsonValidator {
                 CollectorContext.getInstance().add(UnEvaluatedPropertiesValidator.EVALUATED_PROPERTIES, backupEvaluatedProperties);
             }
         }
+        if (!allErrors.isEmpty()) {
+            List<String> childSchemaErrorMessages = allErrors.stream().map(ValidationMessage::getMessage).collect(Collectors.toList());
+            String childMessages = String.join(", ", childSchemaErrorMessages);
+            return Collections.singleton(ValidationMessage.of(getValidatorType().getValue(), ValidatorTypeCode.ANY_OF, at, childMessages));
+        }
         return Collections.unmodifiableSet(allErrors);
     }
 
@@ -129,12 +134,12 @@ public class AnyOfValidator extends BaseJsonValidator implements JsonValidator {
         for (JsonSchema schema : schemas) {
             results.add(schema.walk(node, rootNode, at, shouldValidateSchema));
         }
-        if(! shouldValidateSchema) {
+        if (!shouldValidateSchema) {
             return new LinkedHashSet<>();
         }
         boolean atLeastOneValid = results.stream()
                 .anyMatch(Set::isEmpty);
-        if(atLeastOneValid) {
+        if (atLeastOneValid) {
             return new LinkedHashSet<>();
         }
         return results.stream()
diff --git a/src/main/java/com/networknt/schema/OneOfValidator.java b/src/main/java/com/networknt/schema/OneOfValidator.java
index 0c576b2..2258577 100644
--- a/src/main/java/com/networknt/schema/OneOfValidator.java
+++ b/src/main/java/com/networknt/schema/OneOfValidator.java
@@ -126,7 +126,7 @@ public class OneOfValidator extends BaseJsonValidator implements JsonValidator {
     }
 
     public Set<ValidationMessage> validate(JsonNode node, JsonNode rootNode, String at) {
-        Set<ValidationMessage> errors = new LinkedHashSet<ValidationMessage>();
+        Set<ValidationMessage> errors = new LinkedHashSet<>();
 
         // As oneOf might contain multiple schemas take a backup of evaluatedProperties.
         Object backupEvaluatedProperties = CollectorContext.getInstance().get(UnEvaluatedPropertiesValidator.EVALUATED_PROPERTIES);
@@ -143,14 +143,13 @@ public class OneOfValidator extends BaseJsonValidator implements JsonValidator {
             state.setComplexValidator(true);
 
             int numberOfValidSchema = 0;
-            Set<ValidationMessage> childErrors = new LinkedHashSet<ValidationMessage>();
+            Set<ValidationMessage> childErrors = new LinkedHashSet<>();
             // validate that only a single element has been received in the oneOf node
             // validation should not continue, as it contradicts the oneOf requirement of only one
 //        if(node.isObject() && node.size()>1) {
 //        	errors = Collections.singleton(buildValidationMessage(at, ""));
 //        	return Collections.unmodifiableSet(errors);
 //        }
-
             for (ShortcutValidator validator : schemas) {
                 Set<ValidationMessage> schemaErrors = null;
                 // Reset state in case the previous validator did not match
@@ -191,7 +190,8 @@ public class OneOfValidator extends BaseJsonValidator implements JsonValidator {
             Set<ValidationMessage> childNotRequiredErrors = childErrors.stream().filter(error -> !ValidatorTypeCode.REQUIRED.getValue().equals(error.getType())).collect(Collectors.toSet());
 
             // ensure there is always an "OneOf" error reported if number of valid schemas is not equal to 1.
-            if (numberOfValidSchema > 1) {
+            // TODO We need to break it into two errors in the future.
+            if (numberOfValidSchema != 1) {
                 final ValidationMessage message = getMultiSchemasValidErrorMsg(at);
                 if (failFast) {
                     throw new JsonSchemaException(message);
@@ -199,28 +199,6 @@ public class OneOfValidator extends BaseJsonValidator implements JsonValidator {
                 errors.add(message);
             }
 
-            // ensure there is always an "OneOf" error reported if number of valid schemas is not equal to 1.
-            else if (numberOfValidSchema < 1) {
-                if (!childNotRequiredErrors.isEmpty()) {
-                    childErrors = childNotRequiredErrors;
-                }
-                if (!childErrors.isEmpty()) {
-                    if (childErrors.size() > 1) {
-                        Set<ValidationMessage> notAdditionalPropertiesOnly = new LinkedHashSet<>(childErrors.stream()
-                                .filter((ValidationMessage validationMessage) -> !ValidatorTypeCode.ADDITIONAL_PROPERTIES.getValue().equals(validationMessage.getType()))
-                                .sorted((vm1, vm2) -> compareValidationMessages(vm1, vm2))
-                                .collect(Collectors.toList()));
-                        if (notAdditionalPropertiesOnly.size() > 0) {
-                            childErrors = notAdditionalPropertiesOnly;
-                        }
-                    }
-                    errors.addAll(childErrors);
-                }
-                if (failFast) {
-                    throw new JsonSchemaException(errors.toString());
-                }
-            }
-
             // Make sure to signal parent handlers we matched
             if (errors.isEmpty())
                 state.setMatchedNode(true);
@@ -240,58 +218,12 @@ public class OneOfValidator extends BaseJsonValidator implements JsonValidator {
         }
     }
 
-    /**
-     * Sort <code>ValidationMessage</code> by its type
-     * @return
-     */
-    private static int compareValidationMessages(ValidationMessage vm1, ValidationMessage vm2) {
-        // ValidationMessage's type has smaller index in the list below has high priority
-        final List<String> typeCodes = Arrays.asList(
-                ValidatorTypeCode.TYPE.getValue(),
-                ValidatorTypeCode.DATETIME.getValue(),
-                ValidatorTypeCode.UUID.getValue(),
-                ValidatorTypeCode.ID.getValue(),
-                ValidatorTypeCode.EXCLUSIVE_MAXIMUM.getValue(),
-                ValidatorTypeCode.EXCLUSIVE_MINIMUM.getValue(),
-                ValidatorTypeCode.TRUE.getValue(),
-                ValidatorTypeCode.FALSE.getValue(),
-                ValidatorTypeCode.CONST.getValue(),
-                ValidatorTypeCode.CONTAINS.getValue(),
-                ValidatorTypeCode.PROPERTYNAMES.getValue()
-        );
-
-        final int index1 = typeCodes.indexOf(vm1.getType());
-        final int index2 = typeCodes.indexOf(vm2.getType());
-
-        if (index1 >= 0) {
-            if (index2 >= 0) {
-                return Integer.compare(index1, index2);
-            } else {
-                return -1;
-            }
-        } else {
-            if (index2 >= 0) {
-                return 1;
-            } else {
-                return vm1.getCode().compareTo(vm2.getCode());
-            }
-        }
-    }
-
     private void resetValidatorState() {
         ValidatorState state = (ValidatorState) CollectorContext.getInstance().get(ValidatorState.VALIDATOR_STATE_KEY);
         state.setComplexValidator(false);
         state.setMatchedNode(true);
     }
 
-    public List<JsonSchema> getChildSchemas() {
-        List<JsonSchema> childJsonSchemas = new ArrayList<JsonSchema>();
-        for (ShortcutValidator shortcutValidator: schemas ) {
-            childJsonSchemas.add(shortcutValidator.getSchema());
-        }
-        return childJsonSchemas;
-    }
-
     @Override
     public Set<ValidationMessage> walk(JsonNode node, JsonNode rootNode, String at, boolean shouldValidateSchema) {
         HashSet<ValidationMessage> validationMessages = new LinkedHashSet<ValidationMessage>();
@@ -299,25 +231,21 @@ public class OneOfValidator extends BaseJsonValidator implements JsonValidator {
             validationMessages.addAll(validate(node, rootNode, at));
         } else {
             for (ShortcutValidator validator : schemas) {
-                validator.schema.walk(node, rootNode, at , shouldValidateSchema);
+                validator.schema.walk(node, rootNode, at, shouldValidateSchema);
             }
         }
         return validationMessages;
     }
 
-    private ValidationMessage getMultiSchemasValidErrorMsg(String at){
-        String msg="";
-        for(ShortcutValidator schema: schemas){
-            String schemaValue = schema.getSchema().getSchemaNode().toString();
-            msg = msg.concat(schemaValue);
-        }
-
+    private ValidationMessage getMultiSchemasValidErrorMsg(String at) {
+        List<String> msgStrList = schemas.stream().map(shortcutValidator -> shortcutValidator.getSchema().getSchemaNode().toString()).collect(Collectors.toList());
+        String msg = String.join(", ", msgStrList);
         return ValidationMessage.of(getValidatorType().getValue(), ValidatorTypeCode.ONE_OF, at, msg);
     }
 
     @Override
     public void preloadJsonSchema() {
-        for (final ShortcutValidator scValidator: schemas) {
+        for (final ShortcutValidator scValidator : schemas) {
             scValidator.getSchema().initializeValidators();
         }
     }
diff --git a/src/main/resources/jsv-messages.properties b/src/main/resources/jsv-messages.properties
index 6c7be2f..2f1f19c 100644
--- a/src/main/resources/jsv-messages.properties
+++ b/src/main/resources/jsv-messages.properties
@@ -1,7 +1,7 @@
 $ref = {0}: has an error with 'refs'
 additionalProperties = {0}.{1}: is not defined in the schema and the schema does not allow additional properties
-allOf = {0}: should be valid to all the schemas {1}
-anyOf = {0}: should be valid to any of the schemas {1}
+allOf = {0}: should be valid to all the schemas: {1}
+anyOf = {0}: should be valid to one schema at least: {1}
 const = {0}: must be a constant value {1}
 contains = {0}: does not contain an element that passes these validations: {1}
 crossEdits = {0}: has an error with 'cross edits'
@@ -28,7 +28,7 @@ minimum = {0}: must have a minimum value of {1}
 multipleOf = {0}: must be multiple of {1}
 not = {0}: should not be valid to the schema {1}
 notAllowed = {0}.{1}: is not allowed but it is in the data
-oneOf = {0}: should be valid to one and only one of schema, but more than one are valid: {1}
+oneOf = {0}: should be valid to one and only one of schema, but more than one are valid or no one valid: {1}
 pattern = {0}: does not match the regex pattern {1}
 patternProperties = {0}: has some error with 'pattern properties'
 properties = {0}: has an error with 'properties'


Test patch:
diff --git a/src/test/java/com/networknt/schema/AllOfValidatorTest.java b/src/test/java/com/networknt/schema/AllOfValidatorTest.java
new file mode 100644
index 0000000..91db6b8
--- /dev/null
+++ b/src/test/java/com/networknt/schema/AllOfValidatorTest.java
@@ -0,0 +1,33 @@
+package com.networknt.schema;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.commons.io.FileUtils;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.util.Set;
+
+public class AllOfValidatorTest {
+
+    private static final SpecVersion.VersionFlag SCHEMA_VERSION = SpecVersion.VersionFlag.V201909;
+    private static final JsonSchemaFactory factory = JsonSchemaFactory.getInstance(SCHEMA_VERSION);
+    private static final ObjectMapper mapper = new ObjectMapper();
+
+    public static final String BASE_PATH = "src/test/resources/data/issue520";
+
+    @Test
+    public void validTest() throws IOException {
+        String json = FileUtils.readFileToString(FileUtils.getFile(BASE_PATH, "issue520-allOfValidator-valid.json"), "UTF-8");
+        String schema = FileUtils.readFileToString(FileUtils.getFile(BASE_PATH, "issue520-allOfValidator-schema.json"), "UTF-8");
+        Set<ValidationMessage> validationMessages = factory.getSchema(schema).validate(mapper.readTree(json));
+        System.out.println(validationMessages);
+    }
+
+    @Test
+    public void invalidTest() throws IOException {
+        String json = FileUtils.readFileToString(FileUtils.getFile(BASE_PATH, "issue520-allOfValidator-invalid.json"), "UTF-8");
+        String schema = FileUtils.readFileToString(FileUtils.getFile(BASE_PATH, "issue520-allOfValidator-schema.json"), "UTF-8");
+        Set<ValidationMessage> validationMessages = factory.getSchema(schema).validate(mapper.readTree(json));
+        System.out.println(validationMessages);
+    }
+}
diff --git a/src/test/java/com/networknt/schema/AnyOfValidatorTest.java b/src/test/java/com/networknt/schema/AnyOfValidatorTest.java
new file mode 100644
index 0000000..41b457c
--- /dev/null
+++ b/src/test/java/com/networknt/schema/AnyOfValidatorTest.java
@@ -0,0 +1,33 @@
+package com.networknt.schema;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.commons.io.FileUtils;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.util.Set;
+
+public class AnyOfValidatorTest {
+
+    private static final SpecVersion.VersionFlag SCHEMA_VERSION = SpecVersion.VersionFlag.V201909;
+    private static final JsonSchemaFactory factory = JsonSchemaFactory.getInstance(SCHEMA_VERSION);
+    private static final ObjectMapper mapper = new ObjectMapper();
+
+    public static final String BASE_PATH = "src/test/resources/data/issue520";
+
+    @Test
+    public void validTest() throws IOException {
+        String json = FileUtils.readFileToString(FileUtils.getFile(BASE_PATH, "issue520-anyOfValidator-valid.json"), "UTF-8");
+        String schema = FileUtils.readFileToString(FileUtils.getFile(BASE_PATH, "issue520-anyOfValidator-schema.json"), "UTF-8");
+        Set<ValidationMessage> validationMessages = factory.getSchema(schema).validate(mapper.readTree(json));
+        System.out.println(validationMessages);
+    }
+
+    @Test
+    public void invalidTest() throws IOException {
+        String json = FileUtils.readFileToString(FileUtils.getFile(BASE_PATH, "issue520-anyOfValidator-invalid.json"), "UTF-8");
+        String schema = FileUtils.readFileToString(FileUtils.getFile(BASE_PATH, "issue520-anyOfValidator-schema.json"), "UTF-8");
+        Set<ValidationMessage> validationMessages = factory.getSchema(schema).validate(mapper.readTree(json));
+        System.out.println(validationMessages);
+    }
+}
diff --git a/src/test/java/com/networknt/schema/OneOfValidatorTest.java b/src/test/java/com/networknt/schema/OneOfValidatorTest.java
new file mode 100644
index 0000000..29376b6
--- /dev/null
+++ b/src/test/java/com/networknt/schema/OneOfValidatorTest.java
@@ -0,0 +1,41 @@
+package com.networknt.schema;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.commons.io.FileUtils;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.util.Set;
+
+public class OneOfValidatorTest {
+
+    private static final SpecVersion.VersionFlag SCHEMA_VERSION = SpecVersion.VersionFlag.V201909;
+    private static final JsonSchemaFactory factory = JsonSchemaFactory.getInstance(SCHEMA_VERSION);
+    private static final ObjectMapper mapper = new ObjectMapper();
+
+    public static final String BASE_PATH = "src/test/resources/data/issue520";
+
+    @Test
+    public void validTest() throws IOException {
+        String json = FileUtils.readFileToString(FileUtils.getFile(BASE_PATH, "issue520-oneOfValidator-valid.json"), "UTF-8");
+        String schema = FileUtils.readFileToString(FileUtils.getFile(BASE_PATH, "issue520-oneOfValidator-schema.json"), "UTF-8");
+        Set<ValidationMessage> validationMessages = factory.getSchema(schema).validate(mapper.readTree(json));
+        System.out.println(validationMessages);
+    }
+
+    @Test
+    public void invalid1Test() throws IOException {
+        String json = FileUtils.readFileToString(FileUtils.getFile(BASE_PATH, "issue520-oneOfValidator-invalid-1.json"), "UTF-8");
+        String schema = FileUtils.readFileToString(FileUtils.getFile(BASE_PATH, "issue520-oneOfValidator-schema.json"), "UTF-8");
+        Set<ValidationMessage> validationMessages = factory.getSchema(schema).validate(mapper.readTree(json));
+        System.out.println(validationMessages);
+    }
+
+    @Test
+    public void invalid2Test() throws IOException {
+        String json = FileUtils.readFileToString(FileUtils.getFile(BASE_PATH, "issue520-oneOfValidator-invalid-2.json"), "UTF-8");
+        String schema = FileUtils.readFileToString(FileUtils.getFile(BASE_PATH, "issue520-oneOfValidator-schema.json"), "UTF-8");
+        Set<ValidationMessage> validationMessages = factory.getSchema(schema).validate(mapper.readTree(json));
+        System.out.println(validationMessages);
+    }
+}
diff --git a/src/test/resources/data/issue520/issue520-allOfValidator-invalid.json b/src/test/resources/data/issue520/issue520-allOfValidator-invalid.json
new file mode 100644
index 0000000..825aa0b
--- /dev/null
+++ b/src/test/resources/data/issue520/issue520-allOfValidator-invalid.json
@@ -0,0 +1,3 @@
+{
+  "k3": "v3"
+}
\ No newline at end of file
diff --git a/src/test/resources/data/issue520/issue520-allOfValidator-schema.json b/src/test/resources/data/issue520/issue520-allOfValidator-schema.json
new file mode 100644
index 0000000..159869f
--- /dev/null
+++ b/src/test/resources/data/issue520/issue520-allOfValidator-schema.json
@@ -0,0 +1,25 @@
+{
+  "$id": "http://issue520/schemas/oneOfValidator",
+  "$schema": "https://json-schema.org/draft/2019-09/schema",
+  "type": "object",
+  "properties": {
+    "k1": {
+      "type": "string"
+    },
+    "k2": {
+      "type": "string"
+    }
+  },
+  "allOf": [
+    {
+      "required": [
+        "k1"
+      ]
+    },
+    {
+      "required": [
+        "k2"
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/src/test/resources/data/issue520/issue520-allOfValidator-valid.json b/src/test/resources/data/issue520/issue520-allOfValidator-valid.json
new file mode 100644
index 0000000..9450aeb
--- /dev/null
+++ b/src/test/resources/data/issue520/issue520-allOfValidator-valid.json
@@ -0,0 +1,4 @@
+{
+  "k1": "v1",
+  "k2": "v2"
+}
\ No newline at end of file
diff --git a/src/test/resources/data/issue520/issue520-anyOfValidator-invalid.json b/src/test/resources/data/issue520/issue520-anyOfValidator-invalid.json
new file mode 100644
index 0000000..825aa0b
--- /dev/null
+++ b/src/test/resources/data/issue520/issue520-anyOfValidator-invalid.json
@@ -0,0 +1,3 @@
+{
+  "k3": "v3"
+}
\ No newline at end of file
diff --git a/src/test/resources/data/issue520/issue520-anyOfValidator-schema.json b/src/test/resources/data/issue520/issue520-anyOfValidator-schema.json
new file mode 100644
index 0000000..b902b30
--- /dev/null
+++ b/src/test/resources/data/issue520/issue520-anyOfValidator-schema.json
@@ -0,0 +1,25 @@
+{
+  "$id": "http://issue520/schemas/oneOfValidator",
+  "$schema": "https://json-schema.org/draft/2019-09/schema",
+  "type": "object",
+  "properties": {
+    "k1": {
+      "type": "string"
+    },
+    "k2": {
+      "type": "string"
+    }
+  },
+  "anyOf": [
+    {
+      "required": [
+        "k1"
+      ]
+    },
+    {
+      "required": [
+        "k2"
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/src/test/resources/data/issue520/issue520-anyOfValidator-valid.json b/src/test/resources/data/issue520/issue520-anyOfValidator-valid.json
new file mode 100644
index 0000000..a575ab4
--- /dev/null
+++ b/src/test/resources/data/issue520/issue520-anyOfValidator-valid.json
@@ -0,0 +1,3 @@
+{
+  "k1": "v1"
+}
\ No newline at end of file
diff --git a/src/test/resources/data/issue520/issue520-oneOfValidator-invalid-1.json b/src/test/resources/data/issue520/issue520-oneOfValidator-invalid-1.json
new file mode 100644
index 0000000..825aa0b
--- /dev/null
+++ b/src/test/resources/data/issue520/issue520-oneOfValidator-invalid-1.json
@@ -0,0 +1,3 @@
+{
+  "k3": "v3"
+}
\ No newline at end of file
diff --git a/src/test/resources/data/issue520/issue520-oneOfValidator-invalid-2.json b/src/test/resources/data/issue520/issue520-oneOfValidator-invalid-2.json
new file mode 100644
index 0000000..9450aeb
--- /dev/null
+++ b/src/test/resources/data/issue520/issue520-oneOfValidator-invalid-2.json
@@ -0,0 +1,4 @@
+{
+  "k1": "v1",
+  "k2": "v2"
+}
\ No newline at end of file
diff --git a/src/test/resources/data/issue520/issue520-oneOfValidator-schema.json b/src/test/resources/data/issue520/issue520-oneOfValidator-schema.json
new file mode 100644
index 0000000..e7e6fff
--- /dev/null
+++ b/src/test/resources/data/issue520/issue520-oneOfValidator-schema.json
@@ -0,0 +1,25 @@
+{
+  "$id": "http://issue520/schemas/oneOfValidator",
+  "$schema": "https://json-schema.org/draft/2019-09/schema",
+  "type": "object",
+  "properties": {
+    "k1": {
+      "type": "string"
+    },
+    "k2": {
+      "type": "string"
+    }
+  },
+  "oneOf": [
+    {
+      "required": [
+        "k1"
+      ]
+    },
+    {
+      "required": [
+        "k2"
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/src/test/resources/data/issue520/issue520-oneOfValidator-valid.json b/src/test/resources/data/issue520/issue520-oneOfValidator-valid.json
new file mode 100644
index 0000000..a575ab4
--- /dev/null
+++ b/src/test/resources/data/issue520/issue520-oneOfValidator-valid.json
@@ -0,0 +1,3 @@
+{
+  "k1": "v1"
+}
\ No newline at end of file