this is a dependency-less java 11 based JSON Schema validator with pluggable json parser.
Used by openapi-parser but also usable as standalone JSON Schema validator.
-
supports drafts 2020-12, 2019-09, 7, 6 and 4
-
supports annotations
-
supports the output format: flag, basic & verbose.
-
passes all required tests of the official JSON Schema Test Suite & most optional tests
Vocabularies support is currently limited. Enabling/disabling vocabularies is not yet fully implemented.
It implements the format s as listed. See the limitations below.
-
2020-12 (https://json-schema.org/draft/2020-12/schema)
-
format: see Draft 2019-09 formats
-
-
2019-09 (https://json-schema.org/draft/2019-09/schema)
-
format: duration (not implemented)
-
format: uuid (
jav.util.UUID) -
format: see Draft 7 formats
-
-
draft-07 (https://json-schema.org/draft-07/schema#)
-
contentMediaType: not validated -
contentEncoding: not validated -
format: date (
java.time.LocalDate) -
format: time (
java.time.OffsetTime, see limitations) -
format: idn-email (not implemented)
-
format: idn-hostname (not implemented)
-
format: iri (not implemented)
-
format: iri-reference (not implemented)
-
format: regex (
java.util.regex.Pattern, see limitations) -
format: relative-json-pointer.json (not implemented)
-
format: uri-template.json (not implemented)
-
format: see Draft 6 formats
-
-
draft-06 (https://json-schema.org/draft-06/schema#)
-
format: uri-reference (code)
-
format: json-pointer (not implemented)
-
format: uri-template (not implemented)
-
format: see Draft 4 formats
-
-
draft-04 (http://json-schema.org/draft-04/schema#) ⇒ OpenAPI 3.0.x
-
format: date-time (
java.time.OffsetDateTime, see limitations) -
format: email (code)
-
format: hostname (code)
-
format: ipv4 (code)
-
format: ipv6 (code)
-
format: uri (code)
-
io.openapiprocessor.json-schema-validator uses jdk classes for uri handling & validating format s like, time, date-time, uri & regex assertions where possible to avoid dependencies to other libraries.
Unfortunately the jdk classes do not conform to 100% to their corresponding standards which causes a few limitations and a number of test failures in the optional section of the json-validator test suite:
java.net.URI does not fully support urn: uris. With a bit of custom code the validator supports urn s to pass all tests that use urn s.
-
[draft2020-12|draft2019-09|draft7|draft6|draft4]/optional/ecmascript-regex.json
java.util.regex is not fully compatible with the ECMA 262 (i.e. JavaScript) regular expression dialect.
-
[draft2020-12|draft2019-09|draft7|draft6|draft4]/optional/format/time.json
java.time.format.DateTimeFormatter doesn’t support leap seconds. This causes the leap second specific tests to fail.
package io.openapiprocessor.jsonschema.example;
import io.openapiprocessor.interfaces.Converter;
import io.openapiprocessor.interfaces.ConverterException;
import io.openapiprocessor.jackson.JacksonConverter;
import io.openapiprocessor.jsonschema.ouput.OutputConverter;
import io.openapiprocessor.jsonschema.ouput.OutputUnit;
import io.openapiprocessor.jsonschema.reader.UriReader;
import io.openapiprocessor.jsonschema.schema.*;
import io.openapiprocessor.jsonschema.validator.Validator;
import io.openapiprocessor.jsonschema.validator.ValidatorSettings;
import io.openapiprocessor.jsonschema.validator.steps.ValidationStep;
import org.junit.jupiter.api.Test;
import java.net.URI;
import static io.openapiprocessor.jsonschema.schema.UriSupport.createUri;
public class SetupExampleTest {
@Test
void setupExample() throws ConverterException {
// 1. create a document loader.
// It loads a document by uri and converts it to a Map<String, Object>
// object tree that represents the json or yaml content. The Validator
// operates on that Object tree which makes it independent of the
// object mapper (e.g. jackson, snakeyaml etc.).
// Both (Reader and Converter) have a very simple interface which makes
// it easy to implement your own.
UriReader reader = new UriReader ();
Converter converter = new JacksonConverter ();
DocumentLoader loader = new DocumentLoader (reader, converter);
// 2. create a json schema store, register a schema and get the schema.
// the store creates a JsonSchema object from the schema document. A
// JsonSchema object is a required parameter of the Validator.
// There are several register() methods and convenience functions to
// register json schema draft versions (e.g. 2029-09 etc.).
// Here the store will download the schema from the given uri.
URI schemaUri = createUri ("https://openapiprocessor.io/schemas/mapping/mapping-v3.json");
SchemaStore store = new SchemaStore (loader);
store.register(schemaUri);
// get the json schema object
JsonSchema schema = store.getSchema (schemaUri);
// 3. create an instance. An instance is the document we want to validate
// with the schema. Like the schema above it is a Map<String, Object>
// object tree. DocumentLoader and converter can be used to create the
// Map<String, Object> object tree.
// Here we simply create it from a string using the Converter.
JsonInstance instance = new JsonInstance (converter.convert (
"## simple mapping file\n" +
"\n" +
"openapi-processor-mapping: v3\n" +
"options:\n" +
" package-name: io.openapiprocessor.generated\n" +
" bean-validation: jakarta\n" +
" javadoc: true\n" +
" model-name-suffix: Resource\n" +
" bad: property"
));
// 4. create the validator. The ValidatorSettings are used to enable or
// disable specific formats or set a fallback schema draft version for
// schemas that do not provide a meta schema.
ValidatorSettings settings = new ValidatorSettings ();
Validator validator = new Validator(settings);
// 5. run validation. The result ValidationStep is an implementation
// specific result. It contains all validation details and can be easily
// converted to the official json schema output format.
ValidationStep step = validator.validate(schema, instance);
// boolean valid = step.isValid ();
// 6. convert to official output format. It supports the formats, flag,
// basic and verbose.
OutputConverter output = new OutputConverter(Output.BASIC);
OutputUnit result = output.convert(step);
boolean valid = result.isValid ();
// 7. print errors with error location
if (!valid && result.getErrors () != null) {
System.out.println ("validation failed!");
for (OutputUnit error : result.getErrors ()) {
String schemaLocation = error.getAbsoluteKeywordLocation ();
schemaLocation = schemaLocation.substring (schemaLocation.indexOf ('#'));
String msg = String.format ("%s at instance %s (schema %s)",
error.getError (),
error.getInstanceLocation (),
schemaLocation
);
System.out.println (msg);
}
}
}
}