Repository: networknt/json-schema-validator
Pull request #143 (2019-05-10 19:28:57)

Fix/#142 enum object validation
Related issue: https://github.com/networknt/json-schema-validator/issues/142


Patch:
diff --git a/src/main/java/com/networknt/schema/TypeValidator.java b/src/main/java/com/networknt/schema/TypeValidator.java
index bd5f120..8fd2f06 100644
--- a/src/main/java/com/networknt/schema/TypeValidator.java
+++ b/src/main/java/com/networknt/schema/TypeValidator.java
@@ -24,14 +24,20 @@ import java.util.Collections;
 import java.util.Set;
 
 public class TypeValidator extends BaseJsonValidator implements JsonValidator {
+    private static final String TYPE = "type";
+    private static final String ENUM = "enum";
+    private static final String REF = "$ref";
+
     private static final Logger logger = LoggerFactory.getLogger(TypeValidator.class);
 
     private JsonType schemaType;
+    private JsonSchema parentSchema;
     private UnionTypeValidator unionTypeValidator;
 
     public TypeValidator(String schemaPath, JsonNode schemaNode, JsonSchema parentSchema, ValidationContext validationContext) {
         super(schemaPath, schemaNode, parentSchema, ValidatorTypeCode.TYPE, validationContext);
         schemaType = TypeFactory.getSchemaNodeType(schemaNode);
+        this.parentSchema = parentSchema;
 
         if (schemaType == JsonType.UNION) {
             unionTypeValidator = new UnionTypeValidator(schemaPath, schemaNode, parentSchema, validationContext);
@@ -62,6 +68,11 @@ public class TypeValidator extends BaseJsonValidator implements JsonValidator {
                     return true;
                 }
             }
+            // Skip the type validation when the schema is an enum object schema. Since the current type
+            // of node itself can be used for type validation.
+            if (isEnumObjectSchema(parentSchema)) {
+                return true;
+            }
             if(config.isTypeLoose()) {
                 if (nodeType == JsonType.STRING) {
                     if(schemaType == JsonType.INTEGER) {
@@ -215,4 +226,28 @@ public class TypeValidator extends BaseJsonValidator implements JsonValidator {
         }
         return false;
     }
+
+    private static boolean isEnumObjectSchema(JsonSchema jsonSchema) {
+        // There are three conditions for enum object schema
+        // 1. The current schema contains key "type", and the value is object
+        // 2. The current schema contains key "enum", and the value is an array
+        // 3. The parent schema if refer from components, which means the corresponding enum object class would be generated
+        JsonNode typeNode = null;
+        JsonNode enumNode = null;
+        JsonNode refNode = null;
+
+        if (jsonSchema != null) {
+            if (jsonSchema.getSchemaNode() != null) {
+                typeNode = jsonSchema.getSchemaNode().get(TYPE);
+                enumNode = jsonSchema.getSchemaNode().get(ENUM);
+            }
+            if (jsonSchema.getParentSchema() != null && jsonSchema.getParentSchema().getSchemaNode() != null) {
+                refNode = jsonSchema.getParentSchema().getSchemaNode().get(REF);
+            }
+        }
+        if (typeNode != null && enumNode != null && refNode != null) {
+            return TypeFactory.getSchemaNodeType(typeNode) == JsonType.OBJECT && enumNode.isArray();
+        }
+        return false;
+    }
 }


Test patch:
diff --git a/src/test/java/com/networknt/schema/JsonSchemaTest.java b/src/test/java/com/networknt/schema/JsonSchemaTest.java
index 636f551..97f38f3 100644
--- a/src/test/java/com/networknt/schema/JsonSchemaTest.java
+++ b/src/test/java/com/networknt/schema/JsonSchemaTest.java
@@ -284,6 +284,11 @@ public class JsonSchemaTest {
     public void testUniqueItemsValidator() throws Exception {
         runTestFile("tests/uniqueItems.json");
     }
+
+    @Test
+    public void testEnumObject() throws Exception {
+        runTestFile("tests/enumObject.json");
+    }
     
     @Test
     public void testIdSchemaWithUrl() throws Exception {
diff --git a/src/test/resources/tests/enumObject.json b/src/test/resources/tests/enumObject.json
new file mode 100644
index 0000000..c4ac085
--- /dev/null
+++ b/src/test/resources/tests/enumObject.json
@@ -0,0 +1,68 @@
+[
+  {
+    "description": "simple enum object validation",
+    "schema": {
+      "properties": {
+        "foo": {
+          "type": "object",
+          "enum": [1, 2, 3]
+        },
+        "bar": {
+          "$ref": "#/properties/foo"
+        }
+      }
+    },
+    "tests": [
+      {
+        "description": "one of the enum is valid",
+        "data": {
+          "bar": 1
+        },
+        "valid": true
+      },
+      {
+        "description": "one of the enum is valid",
+        "isTypeLoose": true,
+        "data": {
+          "bar": "1"
+        },
+        "valid": true
+      },
+      {
+        "description": "something else is invalid",
+        "isTypeLoose": false,
+        "data": {
+          "bar": "1"
+        },
+        "valid": false
+      },
+      {
+        "description": "something else is invalid",
+        "data": {
+          "bar": 4
+        },
+        "valid": false
+      }
+    ]
+  },
+  {
+    "description": "fake enum object validation",
+    "schema": {
+          "type": "object",
+          "enum": [1, 2, {"key": "value"}]
+    },
+    "tests": [
+      {
+        "description": "one of the enum is invalid",
+        "data": 1,
+        "valid": false
+      },
+      {
+        "description": "one of the enum is valid",
+        "isTypeLoose": true,
+        "data": {"key": "value"},
+        "valid": true
+      }
+    ]
+  }
+]