config) {
+ /**
+ * Create JsonSchemaReader with provided configuration properties.
+ *
+ *
+ * example:
+ * {@code
+ * JsonSchemaParserConfig config =
+ * new JsonSchemaParserConfig()
+ * .setJsonSchemaVersion(JsonSchemaVersion.SCHEMA_DRAFT_2020_12);
+ * JsonSchemaReader reader = JsonSchemaReader.getReader(config);
+ * }
+ *
+ * @param config the map of configuration properties
+ *
+ * @return new instance of the JsonSchemaReader
+ */
+ static JsonSchemaReader getReader(Map config) {
ServiceLoader loader = ServiceLoader.load(JsonSchemaReader.class);
Iterator iterator = loader.iterator();
diff --git a/src/main/java/es/elixir/bsc/json/schema/JsonSchemaValidationCallback.java b/src/main/java/es/elixir/bsc/json/schema/JsonSchemaValidationCallback.java
index 9435d7e..437c522 100644
--- a/src/main/java/es/elixir/bsc/json/schema/JsonSchemaValidationCallback.java
+++ b/src/main/java/es/elixir/bsc/json/schema/JsonSchemaValidationCallback.java
@@ -1,6 +1,6 @@
/**
* *****************************************************************************
- * Copyright (C) 2022 ELIXIR ES, Spanish National Bioinformatics Institute (INB)
+ * Copyright (C) 2024 ELIXIR ES, Spanish National Bioinformatics Institute (INB)
* and Barcelona Supercomputing Center (BSC)
*
* Modifications to the initial code base are copyright of their respective
@@ -25,7 +25,7 @@
package es.elixir.bsc.json.schema;
-import es.elixir.bsc.json.schema.model.PrimitiveSchema;
+import es.elixir.bsc.json.schema.model.JsonSchema;
import java.util.List;
/**
@@ -39,8 +39,11 @@
public interface JsonSchemaValidationCallback {
/**
- * Callback method called by the validator after the value is validated.Implementations may include custom validation errors into the errors list
- or stop validation process by throwing the ValidationException.
+ * Callback method called by the validator after the value is validated.
+ * Implementations may include custom validation errors into the errors list
+ * or stop validation process by throwing the ValidationException.
+ * Note that validation errors not necessary mean the schema is invalid -
+ * this may be a part of evaluation of 'oneOf', for example.
*
* @param schema json schema model to validate json value.
* @param pointer json pointer to the validated value
@@ -50,5 +53,6 @@ public interface JsonSchemaValidationCallback {
*
* @throws ValidationException the exception to be thrown by the validator.
*/
- void validated(PrimitiveSchema schema, String pointer, T value, T parent, List errors) throws ValidationException;
+ void validated(JsonSchema schema, String pointer, T value, T parent,
+ List errors) throws ValidationException;
}
\ No newline at end of file
diff --git a/src/main/java/es/elixir/bsc/json/schema/impl/DefaultJsonSchemaLocator.java b/src/main/java/es/elixir/bsc/json/schema/impl/DefaultJsonSchemaLocator.java
index 48eb0ed..356f718 100644
--- a/src/main/java/es/elixir/bsc/json/schema/impl/DefaultJsonSchemaLocator.java
+++ b/src/main/java/es/elixir/bsc/json/schema/impl/DefaultJsonSchemaLocator.java
@@ -1,6 +1,6 @@
/**
* *****************************************************************************
- * Copyright (C) 2022 ELIXIR ES, Spanish National Bioinformatics Institute (INB)
+ * Copyright (C) 2024 ELIXIR ES, Spanish National Bioinformatics Institute (INB)
* and Barcelona Supercomputing Center (BSC)
*
* Modifications to the initial code base are copyright of their respective
@@ -59,7 +59,7 @@ public class DefaultJsonSchemaLocator extends JsonSchemaLocator {
protected final Map schemas;
public DefaultJsonSchemaLocator(URI uri) {
- this(uri, new HashMap<>());
+ this(uri, new HashMap());
}
protected DefaultJsonSchemaLocator(URI uri, Map schemas) {
diff --git a/src/main/java/es/elixir/bsc/json/schema/impl/DefaultJsonSchemaParser.java b/src/main/java/es/elixir/bsc/json/schema/impl/DefaultJsonSchemaParser.java
index 950cf52..763ed3e 100644
--- a/src/main/java/es/elixir/bsc/json/schema/impl/DefaultJsonSchemaParser.java
+++ b/src/main/java/es/elixir/bsc/json/schema/impl/DefaultJsonSchemaParser.java
@@ -86,6 +86,9 @@ public AbstractJsonSchema parse(JsonSchemaLocator locator, AbstractJsonSchemaEle
String jsonPointer, JsonValue value, JsonType type)
throws JsonSchemaException {
+ // much easily catch 'invalid' root json pointer here than check for the '/' root in callers.
+ jsonPointer = jsonPointer.startsWith("//") ? jsonPointer.substring(1) : jsonPointer;
+
AbstractJsonSchema schema = cache.get(locator, jsonPointer);
if (schema != null) {
return schema;
diff --git a/src/main/java/es/elixir/bsc/json/schema/impl/DefaultJsonSchemaReader.java b/src/main/java/es/elixir/bsc/json/schema/impl/DefaultJsonSchemaReader.java
index c05a754..10aea74 100644
--- a/src/main/java/es/elixir/bsc/json/schema/impl/DefaultJsonSchemaReader.java
+++ b/src/main/java/es/elixir/bsc/json/schema/impl/DefaultJsonSchemaReader.java
@@ -60,6 +60,11 @@ public void setJsonSchemaParserProperty(String name, Object property) {
properties.put(name, property);
}
+ @Override
+ public JsonSchemaLocator getJsonSchemaLocator(URI uri) {
+ return new DefaultJsonSchemaLocator(uri);
+ }
+
@Override
public JsonSchema read(URL url) throws JsonSchemaException {
try {
diff --git a/src/main/java/es/elixir/bsc/json/schema/model/impl/AbstractJsonSchemaElement.java b/src/main/java/es/elixir/bsc/json/schema/model/impl/AbstractJsonSchemaElement.java
index 7772fdd..0e3e233 100644
--- a/src/main/java/es/elixir/bsc/json/schema/model/impl/AbstractJsonSchemaElement.java
+++ b/src/main/java/es/elixir/bsc/json/schema/model/impl/AbstractJsonSchemaElement.java
@@ -61,9 +61,8 @@ public AbstractJsonSchemaElement(AbstractJsonSchemaElement parent,
JsonSchemaLocator locator, String jsonPointer) {
this.parent = parent;
-
this.locator = locator;
- this.jsonPointer = jsonPointer.startsWith("//") ? jsonPointer.substring(1) : jsonPointer;
+ this.jsonPointer = jsonPointer;
}
@Override
diff --git a/src/main/java/es/elixir/bsc/json/schema/model/impl/JsonNumberSchemaImpl.java b/src/main/java/es/elixir/bsc/json/schema/model/impl/JsonNumberSchemaImpl.java
index d3d06b2..303a193 100644
--- a/src/main/java/es/elixir/bsc/json/schema/model/impl/JsonNumberSchemaImpl.java
+++ b/src/main/java/es/elixir/bsc/json/schema/model/impl/JsonNumberSchemaImpl.java
@@ -92,7 +92,7 @@ public boolean validate(String jsonPointer, JsonValue value, JsonValue parent,
return nerrors == errors.size();
}
-
+
private void validate(String jsonPointer, BigDecimal dec, List errors) {
if (minimum != null) {
diff --git a/src/test/java/es/elixir/bsc/json/schema/JsonSchemaValidationCallbackTest.java b/src/test/java/es/elixir/bsc/json/schema/JsonSchemaValidationCallbackTest.java
index f13df79..60144f9 100644
--- a/src/test/java/es/elixir/bsc/json/schema/JsonSchemaValidationCallbackTest.java
+++ b/src/test/java/es/elixir/bsc/json/schema/JsonSchemaValidationCallbackTest.java
@@ -26,7 +26,6 @@
package es.elixir.bsc.json.schema;
import es.elixir.bsc.json.schema.model.JsonSchema;
-import es.elixir.bsc.json.schema.model.PrimitiveSchema;
import javax.json.Json;
import javax.json.JsonStructure;
import javax.json.JsonValue;
@@ -62,7 +61,8 @@ public void test_01() {
final AtomicInteger counter = new AtomicInteger();
List errors = new ArrayList<>();
- schema.validate(json, errors, (PrimitiveSchema model, String pointer, JsonValue value, JsonValue parent, List err) -> {
+ schema.validate(json, errors, (JsonSchema model, String pointer,
+ JsonValue value, JsonValue parent, List err) -> {
counter.incrementAndGet();
});
diff --git a/src/test/resources/json-schema-org/remotes/draft3/subSchemas.json b/src/test/resources/json-schema-org/remotes/draft3/subSchemas.json
new file mode 100644
index 0000000..6e9b3de
--- /dev/null
+++ b/src/test/resources/json-schema-org/remotes/draft3/subSchemas.json
@@ -0,0 +1,10 @@
+{
+ "definitions": {
+ "integer": {
+ "type": "integer"
+ },
+ "refToInteger": {
+ "$ref": "#/definitions/integer"
+ }
+ }
+}
diff --git a/src/test/resources/json-schema-org/remotes/draft4/locationIndependentIdentifier.json b/src/test/resources/json-schema-org/remotes/draft4/locationIndependentIdentifier.json
new file mode 100644
index 0000000..eeff1eb
--- /dev/null
+++ b/src/test/resources/json-schema-org/remotes/draft4/locationIndependentIdentifier.json
@@ -0,0 +1,11 @@
+{
+ "definitions": {
+ "refToInteger": {
+ "$ref": "#foo"
+ },
+ "A": {
+ "id": "#foo",
+ "type": "integer"
+ }
+ }
+}
diff --git a/src/test/resources/json-schema-org/remotes/draft4/name.json b/src/test/resources/json-schema-org/remotes/draft4/name.json
new file mode 100644
index 0000000..fceacb8
--- /dev/null
+++ b/src/test/resources/json-schema-org/remotes/draft4/name.json
@@ -0,0 +1,15 @@
+{
+ "definitions": {
+ "orNull": {
+ "anyOf": [
+ {
+ "type": "null"
+ },
+ {
+ "$ref": "#"
+ }
+ ]
+ }
+ },
+ "type": "string"
+}
diff --git a/src/test/resources/json-schema-org/remotes/draft4/subSchemas.json b/src/test/resources/json-schema-org/remotes/draft4/subSchemas.json
new file mode 100644
index 0000000..6e9b3de
--- /dev/null
+++ b/src/test/resources/json-schema-org/remotes/draft4/subSchemas.json
@@ -0,0 +1,10 @@
+{
+ "definitions": {
+ "integer": {
+ "type": "integer"
+ },
+ "refToInteger": {
+ "$ref": "#/definitions/integer"
+ }
+ }
+}
diff --git a/src/test/resources/json-schema-org/remotes/draft6/locationIndependentIdentifier.json b/src/test/resources/json-schema-org/remotes/draft6/locationIndependentIdentifier.json
new file mode 100644
index 0000000..e72815c
--- /dev/null
+++ b/src/test/resources/json-schema-org/remotes/draft6/locationIndependentIdentifier.json
@@ -0,0 +1,11 @@
+{
+ "definitions": {
+ "refToInteger": {
+ "$ref": "#foo"
+ },
+ "A": {
+ "$id": "#foo",
+ "type": "integer"
+ }
+ }
+}
diff --git a/src/test/resources/json-schema-org/remotes/draft6/name.json b/src/test/resources/json-schema-org/remotes/draft6/name.json
new file mode 100644
index 0000000..fceacb8
--- /dev/null
+++ b/src/test/resources/json-schema-org/remotes/draft6/name.json
@@ -0,0 +1,15 @@
+{
+ "definitions": {
+ "orNull": {
+ "anyOf": [
+ {
+ "type": "null"
+ },
+ {
+ "$ref": "#"
+ }
+ ]
+ }
+ },
+ "type": "string"
+}
diff --git a/src/test/resources/json-schema-org/remotes/draft6/ref-and-definitions.json b/src/test/resources/json-schema-org/remotes/draft6/ref-and-definitions.json
new file mode 100644
index 0000000..b80deeb
--- /dev/null
+++ b/src/test/resources/json-schema-org/remotes/draft6/ref-and-definitions.json
@@ -0,0 +1,11 @@
+{
+ "$id": "http://localhost:1234/draft6/ref-and-definitions.json",
+ "definitions": {
+ "inner": {
+ "properties": {
+ "bar": { "type": "string" }
+ }
+ }
+ },
+ "allOf": [ { "$ref": "#/definitions/inner" } ]
+}
diff --git a/src/test/resources/json-schema-org/remotes/draft6/subSchemas.json b/src/test/resources/json-schema-org/remotes/draft6/subSchemas.json
new file mode 100644
index 0000000..6e9b3de
--- /dev/null
+++ b/src/test/resources/json-schema-org/remotes/draft6/subSchemas.json
@@ -0,0 +1,10 @@
+{
+ "definitions": {
+ "integer": {
+ "type": "integer"
+ },
+ "refToInteger": {
+ "$ref": "#/definitions/integer"
+ }
+ }
+}
diff --git a/src/test/resources/json-schema-org/remotes/draft7/locationIndependentIdentifier.json b/src/test/resources/json-schema-org/remotes/draft7/locationIndependentIdentifier.json
new file mode 100644
index 0000000..e72815c
--- /dev/null
+++ b/src/test/resources/json-schema-org/remotes/draft7/locationIndependentIdentifier.json
@@ -0,0 +1,11 @@
+{
+ "definitions": {
+ "refToInteger": {
+ "$ref": "#foo"
+ },
+ "A": {
+ "$id": "#foo",
+ "type": "integer"
+ }
+ }
+}
diff --git a/src/test/resources/json-schema-org/remotes/draft7/name.json b/src/test/resources/json-schema-org/remotes/draft7/name.json
new file mode 100644
index 0000000..fceacb8
--- /dev/null
+++ b/src/test/resources/json-schema-org/remotes/draft7/name.json
@@ -0,0 +1,15 @@
+{
+ "definitions": {
+ "orNull": {
+ "anyOf": [
+ {
+ "type": "null"
+ },
+ {
+ "$ref": "#"
+ }
+ ]
+ }
+ },
+ "type": "string"
+}
diff --git a/src/test/resources/json-schema-org/remotes/draft7/ref-and-definitions.json b/src/test/resources/json-schema-org/remotes/draft7/ref-and-definitions.json
new file mode 100644
index 0000000..d592938
--- /dev/null
+++ b/src/test/resources/json-schema-org/remotes/draft7/ref-and-definitions.json
@@ -0,0 +1,11 @@
+{
+ "$id": "http://localhost:1234/draft7/ref-and-definitions.json",
+ "definitions": {
+ "inner": {
+ "properties": {
+ "bar": { "type": "string" }
+ }
+ }
+ },
+ "allOf": [ { "$ref": "#/definitions/inner" } ]
+}
diff --git a/src/test/resources/json-schema-org/remotes/draft7/subSchemas.json b/src/test/resources/json-schema-org/remotes/draft7/subSchemas.json
new file mode 100644
index 0000000..6e9b3de
--- /dev/null
+++ b/src/test/resources/json-schema-org/remotes/draft7/subSchemas.json
@@ -0,0 +1,10 @@
+{
+ "definitions": {
+ "integer": {
+ "type": "integer"
+ },
+ "refToInteger": {
+ "$ref": "#/definitions/integer"
+ }
+ }
+}
diff --git a/src/test/resources/json-schema-org/tests/draft4/refRemote.json b/src/test/resources/json-schema-org/tests/draft4/refRemote.json
index 64a618b..65e4519 100644
--- a/src/test/resources/json-schema-org/tests/draft4/refRemote.json
+++ b/src/test/resources/json-schema-org/tests/draft4/refRemote.json
@@ -17,7 +17,7 @@
},
{
"description": "fragment within remote ref",
- "schema": {"$ref": "http://localhost:1234/subSchemas.json#/definitions/integer"},
+ "schema": {"$ref": "http://localhost:1234/draft4/subSchemas.json#/definitions/integer"},
"tests": [
{
"description": "remote fragment valid",
@@ -34,7 +34,7 @@
{
"description": "ref within remote ref",
"schema": {
- "$ref": "http://localhost:1234/subSchemas.json#/definitions/refToInteger"
+ "$ref": "http://localhost:1234/draft4/subSchemas.json#/definitions/refToInteger"
},
"tests": [
{
@@ -139,7 +139,7 @@
"id": "http://localhost:1234/object",
"type": "object",
"properties": {
- "name": {"$ref": "name.json#/definitions/orNull"}
+ "name": {"$ref": "draft4/name.json#/definitions/orNull"}
}
},
"tests": [
@@ -171,7 +171,7 @@
{
"description": "Location-independent identifier in remote ref",
"schema": {
- "$ref": "http://localhost:1234/locationIndependentIdentifierDraft4.json#/definitions/refToInteger"
+ "$ref": "http://localhost:1234/draft4/locationIndependentIdentifier.json#/definitions/refToInteger"
},
"tests": [
{
diff --git a/src/test/resources/json-schema-org/tests/draft6/refRemote.json b/src/test/resources/json-schema-org/tests/draft6/refRemote.json
index 28459c4..49ead6d 100644
--- a/src/test/resources/json-schema-org/tests/draft6/refRemote.json
+++ b/src/test/resources/json-schema-org/tests/draft6/refRemote.json
@@ -17,7 +17,7 @@
},
{
"description": "fragment within remote ref",
- "schema": {"$ref": "http://localhost:1234/subSchemas.json#/definitions/integer"},
+ "schema": {"$ref": "http://localhost:1234/draft6/subSchemas.json#/definitions/integer"},
"tests": [
{
"description": "remote fragment valid",
@@ -34,7 +34,7 @@
{
"description": "ref within remote ref",
"schema": {
- "$ref": "http://localhost:1234/subSchemas.json#/definitions/refToInteger"
+ "$ref": "http://localhost:1234/draft6/subSchemas.json#/definitions/refToInteger"
},
"tests": [
{
@@ -139,7 +139,7 @@
"$id": "http://localhost:1234/object",
"type": "object",
"properties": {
- "name": {"$ref": "name.json#/definitions/orNull"}
+ "name": {"$ref": "draft6/name.json#/definitions/orNull"}
}
},
"tests": [
@@ -173,7 +173,7 @@
"schema": {
"$id": "http://localhost:1234/schema-remote-ref-ref-defs1.json",
"allOf": [
- { "$ref": "ref-and-definitions.json" }
+ { "$ref": "draft6/ref-and-definitions.json" }
]
},
"tests": [
@@ -196,7 +196,7 @@
{
"description": "Location-independent identifier in remote ref",
"schema": {
- "$ref": "http://localhost:1234/locationIndependentIdentifierPre2019.json#/definitions/refToInteger"
+ "$ref": "http://localhost:1234/draft6/locationIndependentIdentifier.json#/definitions/refToInteger"
},
"tests": [
{
diff --git a/src/test/resources/json-schema-org/tests/draft7/refRemote.json b/src/test/resources/json-schema-org/tests/draft7/refRemote.json
index 22185d6..450787a 100644
--- a/src/test/resources/json-schema-org/tests/draft7/refRemote.json
+++ b/src/test/resources/json-schema-org/tests/draft7/refRemote.json
@@ -17,7 +17,7 @@
},
{
"description": "fragment within remote ref",
- "schema": {"$ref": "http://localhost:1234/subSchemas.json#/definitions/integer"},
+ "schema": {"$ref": "http://localhost:1234/draft7/subSchemas.json#/definitions/integer"},
"tests": [
{
"description": "remote fragment valid",
@@ -34,7 +34,7 @@
{
"description": "ref within remote ref",
"schema": {
- "$ref": "http://localhost:1234/subSchemas.json#/definitions/refToInteger"
+ "$ref": "http://localhost:1234/draft7/subSchemas.json#/definitions/refToInteger"
},
"tests": [
{
@@ -139,7 +139,7 @@
"$id": "http://localhost:1234/object",
"type": "object",
"properties": {
- "name": {"$ref": "name.json#/definitions/orNull"}
+ "name": {"$ref": "draft7/name.json#/definitions/orNull"}
}
},
"tests": [
@@ -173,7 +173,7 @@
"schema": {
"$id": "http://localhost:1234/schema-remote-ref-ref-defs1.json",
"allOf": [
- { "$ref": "ref-and-definitions.json" }
+ { "$ref": "draft7/ref-and-definitions.json" }
]
},
"tests": [
@@ -196,7 +196,7 @@
{
"description": "Location-independent identifier in remote ref",
"schema": {
- "$ref": "http://localhost:1234/locationIndependentIdentifierPre2019.json#/definitions/refToInteger"
+ "$ref": "http://localhost:1234/draft7/locationIndependentIdentifier.json#/definitions/refToInteger"
},
"tests": [
{