Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 

json-schema-validator

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.

features

  • 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

this is ready to try but still work in progress

  • api may change, i.e. improve :-)

  • vocabulary support (enabling/disabling) is not finished

  • not all format validations are implemented

limitations

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)

jdk limitations

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:

general: URI

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.

general/format: ECMAScript regular expressions

  • [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.

format: time

  • [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.

format: date-time

  • [draft2020-12|draft2019-09|draft7|draft6|draft4]/optional/format/date-time.json

java.time.format.DateTimeFormatter doesn’t support leap seconds. This causes the leap second specific tests to fail.

usage

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);
            }
        }
    }
}