Repository: networknt/json-schema-validator
Pull request #645 (2023-01-31 22:41:36)

Add MavenCentral badge to README

codecov-commenter: # [Codecov](https://codecov.io/gh/networknt/json-schema-validator/pull/645?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=networknt) Report
> Merging [#645](https://codecov.io/gh/networknt/json-schema-validator/pull/645?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=networknt) (41ad34d) into [master](https://codecov.io/gh/networknt/json-schema-validator/commit/816c167db8c94804a0bb28f1313847ab27b20451?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=networknt) (816c167) will **not change** coverage.
> The diff coverage is `n/a`.

:mega: This organization is not using Codecov’s [GitHub App Integration](https://github.com/apps/codecov). We recommend you install it so Codecov can continue to function properly for your repositories. [Learn more](https://about.codecov.io/blog/codecov-is-updating-its-github-integration/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=networknt)

```diff
@@            Coverage Diff            @@
##             master     #645   +/-   ##
=========================================
  Coverage     70.79%   70.79%           
  Complexity      985      985           
=========================================
  Files           100      100           
  Lines          3743     3743           
  Branches        779      779           
=========================================
  Hits           2650     2650           
  Misses          818      818           
  Partials        275      275           
```



Help us with your feedback. Take ten seconds to tell us [how you rate us](https://about.codecov.io/nps?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=networknt). Have a feature suggestion? [Share it here.](https://app.codecov.io/gh/feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=networknt)


Patch:
diff --git a/README.md b/README.md
index 8216e2e..7851036 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,9 @@
 [Javadocs](https://www.javadoc.io/doc/com.networknt/json-schema-validator) |
 [Contribution Guide](https://doc.networknt.com/contribute/) |
 
-[![CI](https://github.com/networknt/json-schema-validator/actions/workflows/ci.yml/badge.svg)](https://github.com/networknt/json-schema-validator/actions/workflows/ci.yml) [![codecov.io](https://codecov.io/github/networknt/json-schema-validator/coverage.svg?branch=master)](https://codecov.io/github/networknt/json-schema-validator?branch=master)
+[![CI](https://github.com/networknt/json-schema-validator/actions/workflows/ci.yml/badge.svg)](https://github.com/networknt/json-schema-validator/actions/workflows/ci.yml)
+[![Maven Central](https://img.shields.io/maven-central/v/com.networknt/json-schema-validator.svg)](http://search.maven.org/#search%7Cga%7C1%7Cg%3Acom.networknt%20a%3Ajson-schema-validator)
+[![codecov.io](https://codecov.io/github/networknt/json-schema-validator/coverage.svg?branch=master)](https://codecov.io/github/networknt/json-schema-validator?branch=master)
 
 
 This is a Java implementation of the [JSON Schema Core Draft v4, v6, v7, v2019-09 and v2020-12](http://json-schema.org/latest/json-schema-core.html) specification for JSON schema validation. In addition, it also works for OpenAPI 3.0 request/response validation with some [configuration flags](doc/config.md). For users who want to collect information from a JSON node based on the schema, the [walkers](doc/walkers.md) can help. The default JSON parser is the [Jackson](https://github.com/FasterXML/jackson) that is the most popular one. As it is a key component in our [light-4j](https://github.com/networknt/light-4j) microservices framework to validate request/response against OpenAPI specification for [light-rest-4j](http://www.networknt.com/style/light-rest-4j/) and RPC schema for [light-hybrid-4j](http://www.networknt.com/style/light-hybrid-4j/) at runtime, performance is the most important aspect in the design. 
@@ -88,7 +90,7 @@ Gradle:
 
 ```java
 dependencies {
-    compile(group: "com.networknt", name: "json-schema-validator", version: "1.0.76");
+    compile(group: 'com.networknt', name: 'json-schema-validator', version: '1.0.76');
 }
 ```
 
diff --git a/src/main/java/com/networknt/schema/DateTimeValidator.java b/src/main/java/com/networknt/schema/DateTimeValidator.java
index 3867ec4..8d7fe28 100644
--- a/src/main/java/com/networknt/schema/DateTimeValidator.java
+++ b/src/main/java/com/networknt/schema/DateTimeValidator.java
@@ -29,10 +29,10 @@ import java.util.Set;
 
 public class DateTimeValidator extends BaseJsonValidator implements JsonValidator {
     private static final Logger logger = LoggerFactory.getLogger(DateTimeValidator.class);
+    private static final String DATE = "date";
+    private static final String DATETIME = "date-time";
 
     private final String formatName;
-    private final String DATE = "date";
-    private final String DATETIME = "date-time";
 
     public DateTimeValidator(String schemaPath, JsonNode schemaNode, JsonSchema parentSchema, ValidationContext validationContext, String formatName, ValidatorTypeCode type) {
         super(schemaPath, schemaNode, parentSchema, type, validationContext);
diff --git a/src/main/java/com/networknt/schema/FormatKeyword.java b/src/main/java/com/networknt/schema/FormatKeyword.java
index 279a05c..bb461e9 100644
--- a/src/main/java/com/networknt/schema/FormatKeyword.java
+++ b/src/main/java/com/networknt/schema/FormatKeyword.java
@@ -25,15 +25,15 @@ import java.util.Collections;
 import java.util.Map;
 
 public class FormatKeyword implements Keyword {
+    private static final String DATE = "date";
+    private static final String DATE_TIME = "date-time";
+    private static final String UUID = "uuid";
+    private static final String EMAIL = "email";
+    private static final String DURATION = "duration";
+
     private final ValidatorTypeCode type;
     private final Map<String, Format> formats;
 
-    private final String DATE = "date";
-    private final String DATE_TIME = "date-time";
-    private final String UUID = "uuid";
-    private final String EMAIL = "email";
-    private final String DURATION = "duration";
-
     public FormatKeyword(ValidatorTypeCode type, Map<String, Format> formats) {
         this.type = type;
         this.formats = formats;
diff --git a/src/main/java/com/networknt/schema/JsonSchemaVersion.java b/src/main/java/com/networknt/schema/JsonSchemaVersion.java
index 8d59d34..a43a1d7 100644
--- a/src/main/java/com/networknt/schema/JsonSchemaVersion.java
+++ b/src/main/java/com/networknt/schema/JsonSchemaVersion.java
@@ -4,8 +4,6 @@ import java.util.ArrayList;
 import java.util.List;
 
 public abstract class JsonSchemaVersion {
-    protected static String URI;
-    protected static String ID;
     public static final List<Format> BUILTIN_FORMATS = new ArrayList<Format>(JsonMetaSchema.COMMON_BUILTIN_FORMATS);
     static {
         // add version specific formats here.
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");
     }
 
 }
diff --git a/src/main/java/com/networknt/schema/ValidatorTypeCode.java b/src/main/java/com/networknt/schema/ValidatorTypeCode.java
index d6d1892..11e6557 100644
--- a/src/main/java/com/networknt/schema/ValidatorTypeCode.java
+++ b/src/main/java/com/networknt/schema/ValidatorTypeCode.java
@@ -100,12 +100,12 @@ public enum ValidatorTypeCode implements Keyword, ErrorMessageType {
     DEPENDENT_SCHEMAS("dependentSchemas", "1046", new MessageFormat(I18nSupport.getString("dependentSchemas")), DependentSchemas.class, VersionCode.MinV201909),
     UNEVALUATED_PROPERTIES("unevaluatedProperties","1047",new MessageFormat(I18nSupport.getString("unevaluatedProperties")),UnEvaluatedPropertiesValidator.class, VersionCode.MinV6);
 
-    private static Map<String, ValidatorTypeCode> constants = new HashMap<String, ValidatorTypeCode>();
-    private static SpecVersion specVersion = new SpecVersion();
+    private static final Map<String, ValidatorTypeCode> CONSTANTS = new HashMap<String, ValidatorTypeCode>();
+    private static final SpecVersion SPEC_VERSION = new SpecVersion();
 
     static {
         for (ValidatorTypeCode c : values()) {
-            constants.put(c.value, c);
+            CONSTANTS.put(c.value, c);
         }
     }
 
@@ -131,7 +131,7 @@ public enum ValidatorTypeCode implements Keyword, ErrorMessageType {
     public static List<ValidatorTypeCode> getNonFormatKeywords(SpecVersion.VersionFlag versionFlag) {
         final List<ValidatorTypeCode> result = new ArrayList<ValidatorTypeCode>();
         for (ValidatorTypeCode keyword : values()) {
-            if (!FORMAT.equals(keyword) && specVersion.getVersionFlags(keyword.versionCode).contains(versionFlag)) {
+            if (!FORMAT.equals(keyword) && SPEC_VERSION.getVersionFlags(keyword.versionCode).contains(versionFlag)) {
                 result.add(keyword);
             }
         }
@@ -139,7 +139,7 @@ public enum ValidatorTypeCode implements Keyword, ErrorMessageType {
     }
 
     public static ValidatorTypeCode fromValue(String value) {
-        ValidatorTypeCode constant = constants.get(value);
+        ValidatorTypeCode constant = CONSTANTS.get(value);
         if (constant == null) {
             throw new IllegalArgumentException(value);
         } else {
diff --git a/src/main/java/com/networknt/schema/Version201909.java b/src/main/java/com/networknt/schema/Version201909.java
index e6949a2..8ccc85d 100644
--- a/src/main/java/com/networknt/schema/Version201909.java
+++ b/src/main/java/com/networknt/schema/Version201909.java
@@ -3,7 +3,7 @@ package com.networknt.schema;
 import java.util.Arrays;
 
 public class Version201909 extends JsonSchemaVersion{
-    private static String URI = "https://json-schema.org/draft/2019-09/schema";
+    private static final String URI = "https://json-schema.org/draft/2019-09/schema";
     private static final String ID = "$id";
 
     static {
diff --git a/src/main/java/com/networknt/schema/Version202012.java b/src/main/java/com/networknt/schema/Version202012.java
index c7c1853..6961411 100644
--- a/src/main/java/com/networknt/schema/Version202012.java
+++ b/src/main/java/com/networknt/schema/Version202012.java
@@ -3,7 +3,7 @@ package com.networknt.schema;
 import java.util.Arrays;
 
 public class Version202012 extends JsonSchemaVersion {
-    private static String URI = "https://json-schema.org/draft/2020-12/schema";
+    private static final String URI = "https://json-schema.org/draft/2020-12/schema";
     private static final String ID = "$id";
 
     static {
diff --git a/src/main/java/com/networknt/schema/Version6.java b/src/main/java/com/networknt/schema/Version6.java
index 87200bd..bac1bb8 100644
--- a/src/main/java/com/networknt/schema/Version6.java
+++ b/src/main/java/com/networknt/schema/Version6.java
@@ -3,7 +3,7 @@ package com.networknt.schema;
 import java.util.Arrays;
 
 public class Version6 extends JsonSchemaVersion{
-    private static String URI = "https://json-schema.org/draft-06/schema";
+    private static final String URI = "https://json-schema.org/draft-06/schema";
     // Draft 6 uses "$id"
     private static final String ID = "$id";
 
diff --git a/src/main/java/com/networknt/schema/Version7.java b/src/main/java/com/networknt/schema/Version7.java
index abda1f8..9382631 100644
--- a/src/main/java/com/networknt/schema/Version7.java
+++ b/src/main/java/com/networknt/schema/Version7.java
@@ -3,7 +3,7 @@ package com.networknt.schema;
 import java.util.Arrays;
 
 public class Version7 extends JsonSchemaVersion{
-    private static String URI = "https://json-schema.org/draft-07/schema";
+    private static final String URI = "https://json-schema.org/draft-07/schema";
     private static final String ID = "$id";
 
     static {
diff --git a/src/main/java/com/networknt/schema/format/EmailValidator.java b/src/main/java/com/networknt/schema/format/EmailValidator.java
index 8846ab7..15e92e2 100644
--- a/src/main/java/com/networknt/schema/format/EmailValidator.java
+++ b/src/main/java/com/networknt/schema/format/EmailValidator.java
@@ -58,8 +58,9 @@ public class EmailValidator extends BaseJsonValidator implements JsonValidator {
 
     private static final int MAX_USERNAME_LEN = 64;
 
-    private final boolean allowLocal = false;
-    private final boolean allowTld = false;
+    private static final boolean ALLOW_LOCAL = false;
+    private static final boolean ALLOW_TLD = false;
+
     private final String formatName;
 
 
@@ -114,8 +115,8 @@ public class EmailValidator extends BaseJsonValidator implements JsonValidator {
         }
         // Domain is symbolic name
         DomainValidator domainValidator =
-                DomainValidator.getInstance(allowLocal);
-        if (allowTld) {
+                DomainValidator.getInstance(ALLOW_LOCAL);
+        if (ALLOW_TLD) {
             return domainValidator.isValid(domain) || (!domain.startsWith(".") && domainValidator.isValidTld(domain));
         } else {
             return domainValidator.isValid(domain);


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