diff --git a/docs/utilities/validation.md b/docs/utilities/validation.md
index cc1c71bda..226e10bb6 100644
--- a/docs/utilities/validation.md
+++ b/docs/utilities/validation.md
@@ -83,7 +83,9 @@ You can validate inbound and outbound events using `@Validation` annotation.
You can also use the `Validator#validate()` methods, if you want more control over the validation process such as handling a validation error.
-We support JSON schema version 4, 6, 7 and 201909 (from [jmespath-jackson library](https://github.com/burtcorp/jmespath-java)).
+We support JSON schema version 4, 6, 7, 2019-09 and 2020-12 using the [NetworkNT JSON Schema Validator](https://github.com/networknt/json-schema-validator). ([Compatibility with JSON Schema versions](https://github.com/networknt/json-schema-validator/blob/master/doc/compatibility.md)).
+
+The validator is configured to enable format assertions by default even for 2019-09 and 2020-12.
### Validation annotation
@@ -228,7 +230,8 @@ and [function](https://jmespath.org/tutorial.html#functions) expressions, where
## Change the schema version
-By default, powertools-validation is configured with [V7](https://json-schema.org/draft-07/json-schema-release-notes.html).
+By default, powertools-validation is configured to use [V7](https://json-schema.org/draft-07/json-schema-release-notes.html) as the default dialect if [`$schema`](https://json-schema.org/understanding-json-schema/reference/schema#schema) is not explicitly specified within the schema. If [`$schema`](https://json-schema.org/understanding-json-schema/reference/schema#schema) is explicitly specified within the schema, the validator will use the specified dialect.
+
You can use the `ValidationConfig` to change that behaviour.
=== "Handler with custom schema version"
diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/ValidationALBE2ET.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/ValidationALBE2ET.java
index 324c77a34..41696943a 100644
--- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/ValidationALBE2ET.java
+++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/ValidationALBE2ET.java
@@ -85,7 +85,7 @@ void test_invalidInboundSQSEvent() throws IOException {
// THEN
// invocation should fail inbound validation and return an error message
JsonNode validJsonNode = objectMapper.readTree(invocationResult.getResult());
- assertThat(validJsonNode.get("errorMessage").asText()).contains("$.price: is missing but it is required");
+ assertThat(validJsonNode.get("errorMessage").asText()).contains(": required property 'price' not found");
}
@Test
@@ -99,6 +99,6 @@ void test_invalidOutboundSQSEvent() throws IOException {
// THEN
// invocation should fail outbound validation and return 400
JsonNode validJsonNode = objectMapper.readTree(invocationResult.getResult());
- assertThat(validJsonNode.get("errorMessage").asText()).contains("$.price: must have an exclusive maximum value of 1000");
+ assertThat(validJsonNode.get("errorMessage").asText()).contains("/price: must have an exclusive maximum value of 1000");
}
}
diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/ValidationApiGWE2ET.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/ValidationApiGWE2ET.java
index af7c7d87c..425399c95 100644
--- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/ValidationApiGWE2ET.java
+++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/ValidationApiGWE2ET.java
@@ -86,7 +86,7 @@ void test_invalidInboundApiGWEvent() throws IOException {
// invocation should fail inbound validation and return 400
JsonNode validJsonNode = objectMapper.readTree(invocationResult.getResult());
assertThat(validJsonNode.get("statusCode").asInt()).isEqualTo(400);
- assertThat(validJsonNode.get("body").asText()).contains("$.price: is missing but it is required");
+ assertThat(validJsonNode.get("body").asText()).contains(": required property 'price' not found");
}
@Test
@@ -102,6 +102,6 @@ void test_invalidOutboundApiGWEvent() throws IOException {
JsonNode validJsonNode = objectMapper.readTree(invocationResult.getResult());
assertThat(validJsonNode.get("statusCode").asInt()).isEqualTo(400);
assertThat(validJsonNode.get("body").asText())
- .contains("$.price: must have an exclusive maximum value of 1000");
+ .contains("/price: must have an exclusive maximum value of 1000");
}
}
diff --git a/powertools-validation/pom.xml b/powertools-validation/pom.xml
index 0de38c1c1..fa299b591 100644
--- a/powertools-validation/pom.xml
+++ b/powertools-validation/pom.xml
@@ -65,7 +65,7 @@
com.networknt
json-schema-validator
- 1.0.87
+ 1.4.3
com.amazonaws
diff --git a/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/ValidationConfig.java b/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/ValidationConfig.java
index ccc5a4c2c..3f643ab00 100644
--- a/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/ValidationConfig.java
+++ b/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/ValidationConfig.java
@@ -47,9 +47,15 @@ public SpecVersion.VersionFlag getSchemaVersion() {
}
/**
- * Set the version of the json schema specifications (default is V7)
+ * Set the version of the json schema specifications to use if $schema is not
+ * explicitly specified within the schema (default is V7). If $schema is
+ * explicitly specified within the schema is explicitly specified within the
+ * schema, the validator will use the specified dialect.
*
* @param version May be V4, V6, V7, V201909 or V202012
+ * @see Declaring
+ * a Dialect
*/
public void setSchemaVersion(SpecVersion.VersionFlag version) {
if (version != jsonSchemaVersion) {
diff --git a/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/ValidationUtils.java b/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/ValidationUtils.java
index 221e5fb1d..35b309f07 100644
--- a/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/ValidationUtils.java
+++ b/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/ValidationUtils.java
@@ -21,18 +21,16 @@
import com.fasterxml.jackson.databind.node.JsonNodeType;
import com.fasterxml.jackson.databind.node.NullNode;
import com.networknt.schema.JsonSchema;
+import com.networknt.schema.SchemaLocation;
import com.networknt.schema.SchemaValidatorsConfig;
import com.networknt.schema.ValidationMessage;
-import com.networknt.schema.uri.URITranslator;
import io.burt.jmespath.Expression;
import java.io.ByteArrayOutputStream;
-import java.io.InputStream;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
-import software.amazon.lambda.powertools.validation.internal.ValidationAspect;
/**
* Validation utility, used to manually validate Json against Json Schema
@@ -255,27 +253,26 @@ public static JsonSchema getJsonSchema(String schema, boolean validateSchema) {
private static JsonSchema createJsonSchema(String schema) {
JsonSchema jsonSchema;
+ SchemaValidatorsConfig config = SchemaValidatorsConfig.builder().formatAssertionsEnabled(true)
+ .preloadJsonSchemaRefMaxNestingDepth(10).build();
if (schema.startsWith(CLASSPATH)) {
- String filePath = schema.substring(CLASSPATH.length());
- try (InputStream schemaStream = ValidationAspect.class.getResourceAsStream(filePath)) {
-
- SchemaValidatorsConfig config = new SchemaValidatorsConfig();
- config.addUriTranslator(URITranslator.prefix("https://json-schema.org", "resource:"));
-
- jsonSchema = ValidationConfig.get().getFactory().getSchema(schemaStream, config);
+ try {
+ jsonSchema = ValidationConfig.get().getFactory().getSchema(SchemaLocation.of(schema), config);
} catch (Exception e) {
+ String filePath = schema.substring(CLASSPATH.length());
throw new IllegalArgumentException(
- "'" + schema + "' is invalid, verify '" + filePath + "' is in your classpath");
+ "'" + schema + "' is invalid, verify '" + filePath + "' is in your classpath", e);
}
} else {
- jsonSchema = ValidationConfig.get().getFactory().getSchema(schema);
+ jsonSchema = ValidationConfig.get().getFactory().getSchema(schema, config);
}
return jsonSchema;
}
private static void validateSchema(String schema, JsonSchema jsonSchema) {
- String schemaId = ValidationConfig.get().getSchemaVersion().getId().replace("https://json-schema.org", "");
+ String schemaId = jsonSchema.getValidationContext().getMetaSchema().getIri()
+ .replace("https://json-schema.org", "").replace("http://json-schema.org", "");
try {
validate(jsonSchema.getSchemaNode(),
getJsonSchema(CLASSPATH + schemaId));
diff --git a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/ValidationUtilsTest.java b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/ValidationUtilsTest.java
index d80670669..73c3c6567 100644
--- a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/ValidationUtilsTest.java
+++ b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/ValidationUtilsTest.java
@@ -48,7 +48,7 @@ public void testLoadSchemaV7OK() {
ValidationConfig.get().setSchemaVersion(SpecVersion.VersionFlag.V7);
JsonSchema jsonSchema = getJsonSchema("classpath:/schema_v7.json", true);
assertThat(jsonSchema).isNotNull();
- assertThat(jsonSchema.getCurrentUri()).asString().isEqualTo("http://example.com/product.json");
+ assertThat(jsonSchema.getId()).isEqualTo("http://example.com/product.json");
}
@Test
@@ -57,7 +57,7 @@ public void testLoadSchemaV7KO() {
assertThatThrownBy(() -> getJsonSchema("classpath:/schema_v7_ko.json", true))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage(
- "The schema classpath:/schema_v7_ko.json is not valid, it does not respect the specification /draft-07/schema");
+ "The schema classpath:/schema_v7_ko.json is not valid, it does not respect the specification /draft-07/schema#");
}
@Test
diff --git a/powertools-validation/src/test/resources/schema_v7.json b/powertools-validation/src/test/resources/schema_v7.json
index f38272f2d..e382b8971 100644
--- a/powertools-validation/src/test/resources/schema_v7.json
+++ b/powertools-validation/src/test/resources/schema_v7.json
@@ -1,5 +1,5 @@
{
- "$schema": "http://json-schema.org/draft-07/schema",
+ "$schema": "http://json-schema.org/draft-07/schema#",
"$id": "http://example.com/product.json",
"type": "object",
"title": "Product schema",
diff --git a/powertools-validation/src/test/resources/schema_v7_ko.json b/powertools-validation/src/test/resources/schema_v7_ko.json
index f54bcb3c7..aed187c34 100644
--- a/powertools-validation/src/test/resources/schema_v7_ko.json
+++ b/powertools-validation/src/test/resources/schema_v7_ko.json
@@ -1,5 +1,5 @@
{
- "$schema": "http://json-schema.org/draft-07/schema",
+ "$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"title": "Product schema",
"description": "JSON schema to validate Products",