Repository: networknt/json-schema-validator
Pull request #641 (2023-01-31 17:20:34)

Improve error messages on spec version detection


Patch:
diff --git a/src/main/java/com/networknt/schema/SpecVersionDetector.java b/src/main/java/com/networknt/schema/SpecVersionDetector.java
index 5b79aa9..1d70841 100644
--- a/src/main/java/com/networknt/schema/SpecVersionDetector.java
+++ b/src/main/java/com/networknt/schema/SpecVersionDetector.java
@@ -26,7 +26,6 @@ import com.fasterxml.jackson.databind.JsonNode;
  */
 public class SpecVersionDetector {
 
-    // Schema tag
     private static final String SCHEMA_TAG = "$schema";
 
     /**
@@ -36,25 +35,32 @@ public class SpecVersionDetector {
      * @return Spec version
      */
     public static SpecVersion.VersionFlag detect(JsonNode jsonNode) {
-        if (!jsonNode.has(SCHEMA_TAG))
-            throw new JsonSchemaException("Schema tag not present");
+        JsonNode schemaTag = jsonNode.get(SCHEMA_TAG);
+        if (schemaTag == null) {
+            throw new JsonSchemaException("'" + SCHEMA_TAG + "' tag is not present");
+        }
 
         final boolean forceHttps = true;
         final boolean removeEmptyFragmentSuffix = true;
 
-        String schemaUri = JsonSchemaFactory.normalizeMetaSchemaUri(jsonNode.get(SCHEMA_TAG).asText(), forceHttps, removeEmptyFragmentSuffix);
-        if (schemaUri.equals(JsonMetaSchema.getV4().getUri()))
+        String schemaTagValue = schemaTag.asText();
+        String schemaUri = JsonSchemaFactory.normalizeMetaSchemaUri(schemaTagValue, forceHttps, removeEmptyFragmentSuffix);
+        if (schemaUri.equals(JsonMetaSchema.getV4().getUri())) {
             return SpecVersion.VersionFlag.V4;
-        else if (schemaUri.equals(JsonMetaSchema.getV6().getUri()))
+        }
+        if (schemaUri.equals(JsonMetaSchema.getV6().getUri())) {
             return SpecVersion.VersionFlag.V6;
-        else if (schemaUri.equals(JsonMetaSchema.getV7().getUri()))
+        }
+        if (schemaUri.equals(JsonMetaSchema.getV7().getUri())) {
             return SpecVersion.VersionFlag.V7;
-        else if (schemaUri.equals(JsonMetaSchema.getV201909().getUri()))
+        }
+        if (schemaUri.equals(JsonMetaSchema.getV201909().getUri())) {
             return SpecVersion.VersionFlag.V201909;
-        else if (schemaUri.equals(JsonMetaSchema.getV202012().getUri()))
+        }
+        if (schemaUri.equals(JsonMetaSchema.getV202012().getUri())) {
             return SpecVersion.VersionFlag.V202012;
-        else
-            throw new JsonSchemaException("Unrecognizable schema");
+        }
+        throw new JsonSchemaException("'" + schemaTagValue + "' is unrecognizable schema");
     }
 
 }


Test patch:
diff --git a/src/test/java/com/networknt/schema/SpecVersionDetectorTest.java b/src/test/java/com/networknt/schema/SpecVersionDetectorTest.java
index 3858152..6433709 100644
--- a/src/test/java/com/networknt/schema/SpecVersionDetectorTest.java
+++ b/src/test/java/com/networknt/schema/SpecVersionDetectorTest.java
@@ -2,7 +2,8 @@ package com.networknt.schema;
 
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
-import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -10,75 +11,35 @@ import java.io.InputStream;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 
-public class SpecVersionDetectorTest {
-
-    private static final String SCHEMA_TAG_JSON = "schemaTag.json";
+class SpecVersionDetectorTest {
 
     private static final ObjectMapper mapper = new ObjectMapper();
 
-    @Test
-    public void detectV4() throws IOException {
-        InputStream in = Thread.currentThread().getContextClassLoader()
-                .getResourceAsStream("draft4/" + SCHEMA_TAG_JSON);
-        JsonNode node = mapper.readTree(in);
-        SpecVersion.VersionFlag flag = SpecVersionDetector.detect(node);
-        assertEquals(SpecVersion.VersionFlag.V4, flag);
-    }
-
-    @Test
-    public void detectV6() throws IOException {
+    @ParameterizedTest
+    @CsvSource({
+            "draft4,       V4",
+            "draft6,       V6",
+            "draft7,       V7",
+            "draft2019-09, V201909",
+            "draft2020-12, V202012"
+    })
+    void detectVersion(String resourceDirectory, SpecVersion.VersionFlag expectedFlag) throws IOException {
         InputStream in = Thread.currentThread().getContextClassLoader()
-                .getResourceAsStream("draft6/" + SCHEMA_TAG_JSON);
+                .getResourceAsStream(resourceDirectory + "/schemaTag.json");
         JsonNode node = mapper.readTree(in);
         SpecVersion.VersionFlag flag = SpecVersionDetector.detect(node);
-        assertEquals(SpecVersion.VersionFlag.V6, flag);
+        assertEquals(expectedFlag, flag);
     }
 
-    @Test
-    public void detectV7() throws IOException {
-        InputStream in = Thread.currentThread().getContextClassLoader()
-                .getResourceAsStream("draft7/" + SCHEMA_TAG_JSON);
+    @ParameterizedTest
+    @CsvSource({
+            "data/schemaTag.json,        'http://json-schema.org/draft-03/schema#' is unrecognizable schema",
+            "data/schemaTagMissing.json, '$schema' tag is not present"
+    })
+    void detectInvalidSchemaVersion(String schemaPath, String expectedError) throws IOException {
+        InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(schemaPath);
         JsonNode node = mapper.readTree(in);
-        SpecVersion.VersionFlag flag = SpecVersionDetector.detect(node);
-        assertEquals(SpecVersion.VersionFlag.V7, flag);
+        JsonSchemaException exception = assertThrows(JsonSchemaException.class, () -> SpecVersionDetector.detect(node));
+        assertEquals(expectedError, exception.getMessage());
     }
-
-    @Test
-    public void detectV201909() throws IOException {
-        InputStream in = Thread.currentThread().getContextClassLoader()
-                .getResourceAsStream("draft2019-09/" + SCHEMA_TAG_JSON);
-        JsonNode node = mapper.readTree(in);
-        SpecVersion.VersionFlag flag = SpecVersionDetector.detect(node);
-        assertEquals(SpecVersion.VersionFlag.V201909, flag);
-    }
-
-    @Test
-    public void detectV202012() throws IOException {
-        InputStream in = Thread.currentThread().getContextClassLoader()
-                .getResourceAsStream("draft2020-12/" + SCHEMA_TAG_JSON);
-        JsonNode node = mapper.readTree(in);
-        SpecVersion.VersionFlag flag = SpecVersionDetector.detect(node);
-        assertEquals(SpecVersion.VersionFlag.V202012, flag);
-    }
-
-    @Test
-    public void detectUnsupportedSchemaVersion() {
-        assertThrows(JsonSchemaException.class, () -> {
-            InputStream in = Thread.currentThread().getContextClassLoader()
-                    .getResourceAsStream("data/" + SCHEMA_TAG_JSON);
-            JsonNode node = mapper.readTree(in);
-            SpecVersion.VersionFlag flag = SpecVersionDetector.detect(node);
-        });
-    }
-
-    @Test
-    public void detectMissingSchemaVersion() {
-        assertThrows(JsonSchemaException.class, () -> {
-            InputStream in = Thread.currentThread().getContextClassLoader()
-                    .getResourceAsStream("data/" + "schemaTagMissing.json");
-            JsonNode node = mapper.readTree(in);
-            SpecVersion.VersionFlag flag = SpecVersionDetector.detect(node);
-        });
-    }
-
 }
\ No newline at end of file