NAME

JSON::Schema::Corvus::XS - Fast JSON Schema validation (draft 4 to 2020-12), on the corvus-json-schema C library

SYNOPSIS

use JSON::Schema::Corvus::XS;

my $validator = JSON::Schema::Corvus::XS->compile(<<'JSON');
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": { "id": { "type": "integer", "minimum": 1 } },
  "required": ["id"]
}
JSON

$validator->is_valid_json('{"id": 3}');   # true
$validator->is_valid_json('{"id": 0}');   # false
$validator->is_valid({ id => 3 });        # Perl data: true

my $collector = JSON::Schema::Corvus::XS::ResultsCollector->new('detailed');
$validator->evaluate_json('{"id": "3"}', $collector);
for my $row (@{ $collector->results }) {
  print "$row->{document_evaluation_location}: $row->{message}\n" unless $row->{is_match};
}

DESCRIPTION

A JSON Schema validator for draft 4, 6, 7, 2019-09 and 2020-12, which passes the whole of the JSON-Schema-Test-Suite, with results and annotations. It is a binding to the corvus-json-schema C library, which Alien::CorvusJsonSchema finds or installs. JSON::Schema::Corvus is the same evaluator in pure Perl, with the same API.

JSON text is the main input: it is parsed by the C library, so numbers, strings and booleans are exactly what the text says. Perl data is accepted too, and is encoded to JSON text first, by the rules JSON::PP follows: a scalar that has a number and has never been used as a string is a number, and any other defined scalar is a string; undef is null; JSON::PP::Boolean objects (JSON::PP::true), Perl's own booleans (5.36 and later), \1 and \0 are booleans; an object with a TO_JSON method is encoded as what that returns. The names of an object are written in order of their UTF-8 bytes, so that the order of an evaluation's results does not change from run to run.

A string of JSON text is read as UTF-8: a string with Perl's UTF8 flag on gives its characters, and one without gives its bytes. So pass the bytes read from a file, or a decoded string, but not a string of characters from 128 to 255 that has been downgraded.

METHODS

compile

my $validator = JSON::Schema::Corvus::XS->compile($schema, %options);

Compiles a schema, given as JSON text or as Perl data (a reference, or a boolean). The options:

default_dialect

The dialect of a schema without $schema: draft4, draft6, draft7, draft2019-09 or draft2020-12 (the default).

assert_format

True asserts format, false never does; left out (or undef), it follows the vocabularies (the 2020-12 format-assertion vocabulary asserts, everything else annotates).

assert_format_in_legacy_drafts

With assert_format left out, assert format in drafts 4 to 7 too.

assert_content

Assert contentEncoding and contentMediaType in draft 7, the only draft that asserts them (default true).

formats

Custom format assertions, by name: { even => sub { length($_[0]) % 2 == 0 } }. Each is called with the string (for a number, its JSON text) and returns whether it is valid. One takes precedence over the built-in format of its name.

resolve_document

sub ($uri) for documents a $ref names: it returns the document as JSON text or as Perl data, or undef for a document it does not know. The standard metaschemas are built in.

base_uri

The base URI of the root document.

entry_point

A reference, relative to the root, to evaluate from, such as #/$defs/item.

max_depth

The depth of in-place recursion on a cycle at which evaluation is abandoned (default 128).

pattern_match_limit

The seconds one match of a pattern or patternProperties regular expression against one string may take (default 1). undef or 0 turns the limit off, for a caller who trusts both the schema and the instances.

An exception a custom format or the resolver throws is thrown again by the call that ran it.

compile_uri

my $validator = JSON::Schema::Corvus::XS->compile_uri($uri, %options);

Compiles the schema at an absolute URI, fetched through resolve_document (or one of the standard metaschemas).

Validators

is_valid_json($text)

Whether the JSON text is valid. The text is parsed and evaluated in place, without creating Perl values.

is_valid($data)

Whether the Perl data is valid.

is_valid_document($document)

Whether a "Documents" document is valid.

evaluate_json($text, $collector), evaluate($data, $collector), evaluate_document($document, $collector)

Evaluates every keyword, replacing the collector's results with this evaluation's, and returns whether the instance is valid.

A validator may be used any number of times. Validators, documents and collectors are not copied into new threads (threads): there they are unblessed references to undef, so compile what a thread needs in that thread.

Documents

my $document = JSON::Schema::Corvus::XS::Document->parse($text);
my $document = JSON::Schema::Corvus::XS::Document->from_data($data);

JSON parsed once, for an instance validated more than once.

Results

my $collector = JSON::Schema::Corvus::XS::ResultsCollector->new($level);

A results collector at the basic level (failures, without messages), detailed (failures, with messages, the default) or verbose (every evaluation, passing and failing, with annotations). Its methods:

results

The rows of the last evaluation, as an array of hashes with is_match, message, evaluation_location (the keywords from the root schema), schema_evaluation_location (the schema or keyword within its document) and document_evaluation_location (the JSON pointer of the evaluated value).

annotations, annotations_json

The annotations of a verbose evaluation, grouped by instance location, keyword and schema location: { "/name" => { title => { "#/properties/name" => "Name" } } }, as Perl data or as JSON text.

count, clear

The number of rows, and removing them.

Other functions

JSON::Schema::Corvus::XS::encode_json($data) returns the JSON text (UTF-8 bytes) that the data is validated as. library_version and library_version_string give the C library's version.

ERRORS

Failures are thrown as objects of these classes, which stringify to their message:

JSON::Schema::Corvus::XS::Error

The base class, with message and status (the C library's cjs_status). Thrown itself for a bad argument or option.

JSON::Schema::Corvus::XS::Error::InvalidJson

Text that is not JSON, or not UTF-8. offset is the byte offset at which it was found to be invalid.

JSON::Schema::Corvus::XS::Error::Compilation

A schema that does not compile: a reference that does not resolve, or a regular expression that is not valid.

JSON::Schema::Corvus::XS::Error::PatternTooLarge

A Compilation error for a regular expression over a limit of size: 1,048,576 bytes of pattern, 1,000 levels of groups, or 1,048,576 bytes counted for it as it is read.

JSON::Schema::Corvus::XS::Error::Depth

Evaluation recursed in place beyond max_depth.

JSON::Schema::Corvus::XS::Error::PatternMatchLimit

A match of a regular expression reached pattern_match_limit: the instance is neither valid nor not valid. Compiling can throw it too, since a pattern of patternProperties is matched against the names the schema declares.

Perl data that has no JSON form (a code reference, an object with no TO_JSON, a number that is not finite, or a structure nested more than 512 deep) dies with a message.

SEE ALSO

JSON::Schema::Corvus, Alien::CorvusJsonSchema, https://github.com/corvus-dotnet/Corvus.JsonSchema.

LICENSE

Apache License 2.0.