JSON::Schema::Modern::Utilities(3pm)

NAME
JSON::Schema::Modern::Utilities - Internal utilities for JSON::Schema::Modern

VERSION
version 0.641

SYNOPSIS
  use JSON::Schema::Modern::Utilities qw(func1 func2..);

DESCRIPTION
This class contains internal utilities to be used by JSON::Schema::Modern, and other useful helpers.

FUNCTIONS

  is_type
  if (is_type('string', $value)) { ... }

Returns a boolean indicating whether the provided value is of the specified core type ("null", "boolean", "string", "number", "object", "array") or "integer". Also optionally takes a hashref "{ legacy_ints =" 1 }> indicating that draft4 number semantics should apply (where unlike later drafts, 2.0 is not an integer).

  get_type
  my $type = get_type($value);

Returns one of the core types ("null", "boolean", "string", "number", "object", "array") or "integer". Also optionally takes a hashref "{ legacy_ints =" 1 }> indicating that draft4 number semantics should apply. Behaviour is consistent with "is_type".

  is_bool
  if (is_bool($value)) { ... }

Equivalent to "is_type('boolean', $value)". Accepts JSON booleans and builtin booleans, but not dualvars (because JSON encoders do not recognize these as booleans).

  is_schema
  if (is_schema($value)) { ... }

Equivalent to "is_type('object') || is_type('boolean')".

  is_equal
  if (not is_equal($x, $y, my $state = {})) {
    say "values differ starting at $state->{path}: $state->{error}";
  }

Compares two arbitrary data payloads for equality, as per Instance Equality in the JSON Schema draft2020-12 specification <https://json-schema.org/draft/2020-12/json-schema-core.html#rfc.section.4.2.2>.

The optional third argument hashref supports the following fields:

•   "scalarref_booleans" (provided by caller input): as in "scalarref_booleans" in JSON::Schema::Modern

•   "stringy_numbers" (provided by caller input): when set, strings will also be compared numerically, as in "stringy_numbers" in JSON::Schema::Modern

•   "path" (populated by function): if result is false, the json pointer location of the first difference

•   "error" (populated by function): if result is false, an error description of the first difference

  is_elements_unique
  if (not is_elements_unique($arrayref, my $state = {}) {
    say "lists differ starting at $state->{path}: $state->{error}";
  }

Compares all elements of an arrayref for uniqueness.

The optional second argument hashref supports the same options as "is_equal", plus:

•   "equal_indices" (populated by function): if result is false, the list of indices of the (first set of) equal items found.

  jsonp
  # '/paths/~1foo~1{foo_id}/get/responses'
  my $jsonp = jsonp(qw(/paths /foo/{foo_id} get responses));

Constructs a json pointer string from a list of path components, with correct escaping; the first argument must be '' or an already-escaped json pointer, to which the rest of the path components are appended.

  unjsonp
  # ('', 'paths', '/foo/{foo_id}', 'get', 'responses')
  my @components = unjsonp('/paths/~1foo~1{foo_id}/get/responses');

Splits a json pointer string into its path components, with correct unescaping.

  jsonp_get
  # 4
  my $val = jsonp_get({ a => 1, b => { c => 3, d => 4 } }, '/b/d');

Fetches the value of a data structure at a particular json pointer location.

  jsonp_elements
  # {
  #   '/a/b/0' => 'x',
  #   '/a/b/1' => 'y',
  #   '/a/c/d' => 'e',
  # }
  jsonp_elements({ a => { b => [ 'x', 'y' ], c => { d => 'e' } } });

Fetches all the ( json pointer => value ) tuples of a data structure as a hashref.

  jsonp_set
  my $data = { a => 1, b => { c => 3, d => 4 } };
  my $defaults = {
    '/b/d' => 5,
    '/b/e' => 6,
    '/f' => 7,
    '/g/h/i/1' => [ 10 ],
  };
  jsonp_set($data, $_, $defaults->{$_}) foreach keys %$defaults;

  # data is now:
  # { a => 1, b => { c => 3, d => 5, e => 6 }, f => 7, g => { h => { i => [ undef, [ 10 ] ] } } }

Given an arbitrary data structure, a json pointer string, and an arbitrary value, assigns that value to the given position in the data structure. This is a destructive operation, overwriting whatever data was there before if needed (even if an incompatible type: e.g. a hash key will overwrite an existing arrayref). Intermediary keys or indexes will spring into existence as needed.

  json_pointer_type
A Type::Tiny type representing a json pointer string.

  canonical_uri_type
A Type::Tiny type representing a canonical URI: a Mojo::URL with either no fragment, or with a json pointer fragment.

  core_types_type
A Type::Tiny type representing the core JSON Schema types.

  core_formats_type
A Type::Tiny type representing the core JSON Schema formats (across all supported versions).

  load_cached_document
  my $evaluator = JSON::Schema::Modern->new;
  my $uri = 'https://json-schema.org/draft-07/schema#';
  my $document = load_cached_document($evaluator, $uri);

  my $result = $evaluator->evaluate($data, $uri);

Loads a document object from global cache, loading data from disk if needed. This should only be used for officially-published schemas and metaschemas that are bundled with this distribution or another related one.

  add_media_type
  add_media_type('application/my_zip', $decoder_sub, $encoder_sub);
  add_media_type('audio/*; version=1', $decoder_sub, $encoder_sub);

Adds a media-type entry to the registry, or replaces an existing one. This registry is runtime-global, available to any code running in this process.

Either or both of the subrefs are optional (use "undef" for the decoder sub if you only want an encoder); the subref is expected to have the following signature:

  sub ($content_ref, $parameters = {}, @)

The subref will be called with a reference to the content string, and a hashref of the parameters that were parsed from the "Content-Type" header (if any). Extra arguments are allowed to allow for future flexibility with this interface.

These media types are already defined:

•   "application/json" (RFC 4627) <https://datatracker.ietf.org/doc/html/rfc4627>

•   "application/schema+json" (proposed definition) <https://json-schema.org/draft/2020-12/json-schema-core.html#name-application-schemajson>

•   "application/schema-instance+json" (proposed definition) <https://json-schema.org/draft/2020-12/json-schema-core.html#name-application-schema-instance>

•   "application/octet-stream" - passes strings through unchanged

•   "application/x-www-form-urlencoded" (WHATWG) <https://url.spec.whatwg.org/#application/x-www-form-urlencoded>

•   "application/x-ndjson" (spec) <https://github.com/ndjson/ndjson-spec>

•   "text/*" - passes strings through unchanged; supports the charset parameter

Media-type definitions can be overridden with a new call to "add_media_type".

See the official OpenAPI Media Type Registry <https://spec.openapis.org/registry/media-type> for a registry of known and useful media types; for compatibility reasons, avoid defining a media type listed here with different semantics.

  delete_media_type
  delete_media_type('application/my_zip');

Removes a media-type entry from the registry. The string must match exactly, including case and whitespace.

  decode_media_type
  my $content_ref = decode_media_type('text/plain; charset=UTF-8', \'encoded text');

Finds the best-matching media-type decoder for the given media-type and decodes the content (which must be passed as a reference); returns a reference to the decoded content, or "undef" if no matching decoder could be found. An exception might be thrown if the data could not be successfully decoded.

  encode_media_type
  my $content_ref = encode_media_type('text/plain; charset=UTF-8', \[ 'decoded content' ]);

Finds the best-matching media-type encoder for the given media-type and encodes the content (which must be passed as a reference); returns a reference to the encoded content, or "undef" if no matching encoder could be found. An exception might be thrown if the data could not be successfully encoded.

  match_media_type
  my $registered_media_type = match_media_type('text/html');
  my $ad_hoc_media_type = match_media_type('text/html', [ 'text/plain', 'text/*' ]);

Finds the best match for a "Content-Type" header value from the media-types in the registry, or from an ad-hoc list reference provided in the remaining arguments.

Types with structured suffixes will match more generic types when an exact match is not available (e.g. "application/schema+json" will match an entry for "application/json").

Exact matches to the "type/subtype" name are preferred over wildcard matches (e.g. "text/*"); if parameters are present in the value being matched against (the list of registered media-types, or the list provided to this sub), all parameters must be present and match exactly.

All comparisons are done case-insensitively.

GIVING THANKS
If you found this module to be useful, please show your appreciation by adding a +1 in MetaCPAN <https://metacpan.org/dist/JSON-Schema-Modern> and a star in GitHub <https://github.com/karenetheridge/JSON-Schema-Modern>.

SUPPORT
Bugs may be submitted through <https://github.com/karenetheridge/JSON-Schema-Modern/issues>.

I am also usually active on irc, as 'ether' at "irc.perl.org" and "irc.libera.chat".

You can also find me on the JSON Schema Slack server <https://json-schema.slack.com> and OpenAPI Slack server <https://open-api.slack.com>, which are also great resources for finding help.

AUTHOR
Karen Etheridge <ether@cpan.org>

COPYRIGHT AND LICENCE
This software is copyright (c) 2020 by Karen Etheridge.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.

Some schema files have their own licence, in share/LICENSE.