Hello community, here is the log from the commit of package perl-JSON-Validator for openSUSE:Factory checked in at 2020-10-26 16:18:04 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/perl-JSON-Validator (Old) and /work/SRC/openSUSE:Factory/.perl-JSON-Validator.new.3463 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "perl-JSON-Validator" Mon Oct 26 16:18:04 2020 rev:26 rq:841735 version:4.10 Changes: -------- --- /work/SRC/openSUSE:Factory/perl-JSON-Validator/perl-JSON-Validator.changes 2020-10-13 15:46:38.373475447 +0200 +++ /work/SRC/openSUSE:Factory/.perl-JSON-Validator.new.3463/perl-JSON-Validator.changes 2020-10-26 16:19:16.419077992 +0100 @@ -1,0 +2,12 @@ +Wed Oct 14 03:11:25 UTC 2020 - Tina Müller <timueller+p...@suse.de> + +- updated to 4.10 + see /usr/share/doc/packages/perl-JSON-Validator/Changes + + 4.10 2020-10-13T10:53:11+0900 + - Add JSON::Validator::Store + - Changed JSON::Validator->schema() to also load + - JSON::Validator->schema() can handle draft 2019-09 schemas + - Documented what is not supported in draft 2019-09 + +------------------------------------------------------------------- Old: ---- JSON-Validator-4.09.tar.gz New: ---- JSON-Validator-4.10.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ perl-JSON-Validator.spec ++++++ --- /var/tmp/diff_new_pack.duymTN/_old 2020-10-26 16:19:17.415078793 +0100 +++ /var/tmp/diff_new_pack.duymTN/_new 2020-10-26 16:19:17.419078796 +0100 @@ -17,7 +17,7 @@ Name: perl-JSON-Validator -Version: 4.09 +Version: 4.10 Release: 0 %define cpan_name JSON-Validator Summary: Validate data against a JSON schema ++++++ JSON-Validator-4.09.tar.gz -> JSON-Validator-4.10.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/JSON-Validator-4.09/Changes new/JSON-Validator-4.10/Changes --- old/JSON-Validator-4.09/Changes 2020-10-12 04:04:16.000000000 +0200 +++ new/JSON-Validator-4.10/Changes 2020-10-13 03:53:11.000000000 +0200 @@ -1,5 +1,11 @@ Revision history for perl distribution JSON-Validator +4.10 2020-10-13T10:53:11+0900 + - Add JSON::Validator::Store + - Changed JSON::Validator->schema() to also load + - JSON::Validator->schema() can handle draft 2019-09 schemas + - Documented what is not supported in draft 2019-09 + 4.09 2020-10-12T11:04:16+0900 - Fix handling if "id" and "$id" in subschemas #186 - Add CONTRIBUTING.md #161 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/JSON-Validator-4.09/MANIFEST new/JSON-Validator-4.10/MANIFEST --- old/JSON-Validator-4.09/MANIFEST 2020-10-12 04:04:17.000000000 +0200 +++ new/JSON-Validator-4.10/MANIFEST 2020-10-13 03:53:12.000000000 +0200 @@ -27,6 +27,7 @@ lib/JSON/Validator/Schema/Draft4.pm lib/JSON/Validator/Schema/Draft6.pm lib/JSON/Validator/Schema/Draft7.pm +lib/JSON/Validator/Store.pm lib/JSON/Validator/Util.pm Makefile.PL MANIFEST This list of files diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/JSON-Validator-4.09/META.json new/JSON-Validator-4.10/META.json --- old/JSON-Validator-4.09/META.json 2020-10-12 04:04:17.000000000 +0200 +++ new/JSON-Validator-4.10/META.json 2020-10-13 03:53:12.000000000 +0200 @@ -63,6 +63,6 @@ }, "x_IRC" : "irc://irc.freenode.net/#mojo" }, - "version" : "4.09", + "version" : "4.10", "x_serialization_backend" : "JSON::PP version 4.04" } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/JSON-Validator-4.09/META.yml new/JSON-Validator-4.10/META.yml --- old/JSON-Validator-4.09/META.yml 2020-10-12 04:04:17.000000000 +0200 +++ new/JSON-Validator-4.10/META.yml 2020-10-13 03:53:12.000000000 +0200 @@ -32,5 +32,5 @@ homepage: https://mojolicious.org license: http://www.opensource.org/licenses/artistic-license-2.0 repository: https://github.com/mojolicious/json-validator.git -version: '4.09' +version: '4.10' x_serialization_backend: 'CPAN::Meta::YAML version 0.018' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/JSON-Validator-4.09/lib/JSON/Validator/Schema/Draft201909.pm new/JSON-Validator-4.10/lib/JSON/Validator/Schema/Draft201909.pm --- old/JSON-Validator-4.09/lib/JSON/Validator/Schema/Draft201909.pm 2020-10-12 03:20:53.000000000 +0200 +++ new/JSON-Validator-4.10/lib/JSON/Validator/Schema/Draft201909.pm 2020-10-13 02:39:39.000000000 +0200 @@ -35,7 +35,7 @@ if ($topic->{'$id'} and !ref $topic->{'$id'}) { my $id = Mojo::URL->new($topic->{'$id'}); $id = $id->to_abs($base_url) unless $id->is_abs; - $self->_store($id->to_string => $topic); + $self->store->add($id->to_string => $topic); $base_url = $id; } @@ -151,6 +151,36 @@ This class represents L<https://json-schema.org/specification-links.html#2019-09-formerly-known-as-draft-8>. +Support for parsing the draft is not yet complete. Look at +L<https://github.com/mojolicious/json-validator/blob/master/t/draft2019-09-acceptance.t> +for the most recent overview of what is not yet supported. + +Currently less than 1% of the official test suite gets skipped. Here is a list of known +limitations: + +=over 2 + +=item * Float and integers are equal up to 64-bit representation limits + +This module is unable to say that the 64-bit number "9007199254740992.0" is the +same as "9007199254740992". + +=item * unevaluatedItems + +See L</unevaluatedProperties> + +=item * unevaluatedProperties + +L</unevaluatedItems> and L</unevaluatedProperties> needs to track what has been +valdated or not using annotations. This is not yet supported. + +=item * $recursiveAnchor + +Basic support for C<$recursiveRef> is supported, but using it together with +C<$recursiveAnchor> is not. + +=back + =head1 ATTRIBUTES =head2 specification diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/JSON-Validator-4.09/lib/JSON/Validator/Store.pm new/JSON-Validator-4.10/lib/JSON/Validator/Store.pm --- old/JSON-Validator-4.09/lib/JSON/Validator/Store.pm 1970-01-01 01:00:00.000000000 +0100 +++ new/JSON-Validator-4.10/lib/JSON/Validator/Store.pm 2020-10-13 03:35:10.000000000 +0200 @@ -0,0 +1,239 @@ +package JSON::Validator::Store; +use Mojo::Base -base; + +use Mojo::Exception qw(raise); +use Mojo::File qw(path); +use Mojo::JSON; +use Mojo::UserAgent; +use Mojo::Util qw(url_unescape); +use JSON::Validator::Schema; +use JSON::Validator::Util qw(data_section); + +use constant BUNDLED_PATH => path(path(__FILE__)->dirname, 'cache')->to_string; +use constant CASE_TOLERANT => File::Spec->case_tolerant; + +has cache_paths => sub { [split(/:/, $ENV{JSON_VALIDATOR_CACHE_PATH} || ''), BUNDLED_PATH] }; +has schemas => sub { +{} }; + +has ua => sub { + my $ua = Mojo::UserAgent->new; + $ua->proxy->detect; + return $ua->max_redirects(3); +}; + +sub add { + my ($self, $id, $schema) = @_; + $id =~ s!(.)#$!$1!; + $self->schemas->{$id} = $schema; + return $id; +} + +sub exists { + my ($self, $id) = @_; + return undef unless defined $id; + $id =~ s!(.)#$!$1!; + return $self->schemas->{$id} && $id; +} + +sub get { + my ($self, $id) = @_; + return undef unless defined $id; + $id =~ s!(.)#$!$1!; + return $self->schemas->{$id}; +} + +sub load { + return + $_[0]->_load_from_url($_[1]) + || $_[0]->_load_from_data($_[1]) + || $_[0]->_load_from_text($_[1]) + || $_[0]->_load_from_file($_[1]) + || $_[0]->_load_from_app($_[1]) + || $_[0]->get($_[1]) + || raise 'JSON::Validator::Exception', "Unable to load schema $_[1]"; +} + +sub _load_from_app { + return undef unless $_[1] =~ m!^/!; + + my ($self, $url, $id) = @_; + return $id if $id = $self->exists($url); + + my $tx = $self->ua->get($url); + my $err = $tx->error && $tx->error->{message}; + raise 'JSON::Validator::Exception', $err if $err; + return $self->add($url => _parse($tx->res->body)); +} + +sub _load_from_data { + return undef unless $_[1] =~ m!^data://([^/]*)/(.*)!; + + my ($self, $url, $id) = @_; + return $id if $id = $self->exists($url); + + my ($class, $file) = ($1, $2); # data://([^/]*)/(.*) + my $text = data_section $class, $file, {encoding => 'UTF-8'}; + raise 'JSON::Validator::Exception', "Could not find $url" unless $text; + return $self->add($url => _parse($text)); +} + +sub _load_from_file { + my ($self, $file) = @_; + + $file =~ s!^file://!!; + $file =~ s!#$!!; + $file = path(split '/', url_unescape $file); + return undef unless -e $file; + + $file = $file->realpath; + my $id = Mojo::URL->new->scheme('file')->host('')->path(CASE_TOLERANT ? lc $file : "$file"); + return $self->exists($id) || $self->add($id => _parse($file->slurp)); +} + +sub _load_from_text { + my ($self, $text) = @_; + my $is_scalar_ref = ref $text eq 'SCALAR'; + return undef unless $is_scalar_ref or $text =~ m!^\s*(?:---|\{)!s; + + my $id = sprintf 'urn:text:%s', Mojo::Util::md5_sum($is_scalar_ref ? $$text : $text); + return $self->exists($id) || $self->add($id => _parse($is_scalar_ref ? $$text : $text)); +} + +sub _load_from_url { + return undef unless $_[1] =~ m!^https?://!; + + my ($self, $url, $id) = @_; + return $id if $id = $self->exists($url); + + $url = Mojo::URL->new($url)->fragment(undef); + return $id if $id = $self->exists($url); + + my $cache_path = $self->cache_paths->[0]; + my $cache_file = Mojo::Util::md5_sum("$url"); + for (@{$self->cache_paths}) { + my $path = path $_, $cache_file; + return $self->add($url => _parse($path->slurp)) if -r $path; + } + + my $tx = $self->ua->get($url); + my $err = $tx->error && $tx->error->{message}; + raise 'JSON::Validator::Exception', $err if $err; + + if ($cache_path and $cache_path ne BUNDLED_PATH and -w $cache_path) { + $cache_file = path $cache_path, $cache_file; + $cache_file->spurt($tx->res->body); + } + + return $self->add($url => _parse($tx->res->body)); +} + +sub _parse { + return Mojo::JSON::decode_json($_[0]) if $_[0] =~ m!^\s*\{!s; + return JSON::Validator::Util::_yaml_load($_[0]); +} + +1; + +=encoding utf8 + +=head1 NAME + +JSON::Validator::Store - Load and caching JSON schemas + +=head1 SYNOPSIS + + use JSON::Validator; + my $jv = JSON::Validator->new; + $jv->store->add("urn:uuid:ee564b8a-7a87-4125-8c96-e9f123d6766f" => {...}); + $jv->store->load("http://api.example.com/my/schema.json"); + +=head1 DESCRIPTION + +L<JSON::Validator::Store> is a class for loading and caching JSON-Schemas. + +=head1 ATTRIBUTES + +=head2 cache_paths + + my $store = $store->cache_paths(\@paths); + my $array_ref = $store->cache_paths; + +A list of directories to where cached specifications are stored. Defaults to +C<JSON_VALIDATOR_CACHE_PATH> environment variable and the specs that is bundled +with this distribution. + +C<JSON_VALIDATOR_CACHE_PATH> can be a list of directories, each separated by ":". + +See L<JSON::Validator/Bundled specifications> for more details. + +=head2 schemas + + my $hash_ref = $store->schemas; + my $store = $store->schemas({}); + +Hold the schemas as data structures. The keys are schema "id". + +=head2 ua + + my $ua = $store->ua; + my $store = $store->ua(Mojo::UserAgent->new); + +Holds a L<Mojo::UserAgent> object, used by L</schema> to load a JSON schema +from remote location. + +The default L<Mojo::UserAgent> will detect proxy settings and have +L<Mojo::UserAgent/max_redirects> set to 3. + +=head1 METHODS + +=head2 add + + my $normalized_id = $store->add($id => \%schema); + +Used to add a schema data structure. Note that C<$id> might not be the same as +C<$normalized_id>. + +=head2 exists + + my $normalized_id = $store->exists($id); + +Returns a C<$normalized_id> if it is present in the L</schemas>. + +=head2 get + + my $schema = $store->get($normalized_id); + +Used to retrieve a C<$schema> added by L</add> or L</load>. + +=head2 load + + my $normalized_id = $store->load('https://...'); + my $normalized_id = $store->load('data://main/foo.json'); + my $normalized_id = $store->load('---\nid: yaml'); + my $normalized_id = $store->load('{"id":"yaml"}'); + my $normalized_id = $store->load(\$text); + my $normalized_id = $store->load('/path/to/foo.json'); + my $normalized_id = $store->load('file:///path/to/foo.json'); + my $normalized_id = $store->load('/load/from/ua-server-app'); + +Can load a C<$schema> from many different sources. The input can be a string or +a string-like object, and the L</load> method will try to resolve it in the +order listed in above. + +Loading schemas from C<$text> will generate an C<$normalized_id> in L</schemas> +looking like "urn:text:$text_checksum". This might change in the future! + +Loading files from disk will result in a C<$normalized_id> that always start +with "file://". + +Loading can also be done with relative path, which will then load from: + + $store->ua->server->app; + +This method is EXPERIMENTAL, but unlikely to change significantly. + +=head1 SEE ALSO + +L<JSON::Validator>. + +=cut diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/JSON-Validator-4.09/lib/JSON/Validator.pm new/JSON-Validator-4.10/lib/JSON/Validator.pm --- old/JSON-Validator-4.09/lib/JSON/Validator.pm 2020-10-12 04:04:16.000000000 +0200 +++ new/JSON-Validator-4.10/lib/JSON/Validator.pm 2020-10-13 03:53:11.000000000 +0200 @@ -2,42 +2,44 @@ use Mojo::Base -base; use Exporter 'import'; -use Carp 'confess'; +use Carp qw(confess); use JSON::Validator::Formats; -use JSON::Validator::Joi; use JSON::Validator::Ref; -use JSON::Validator::Schema; -use JSON::Validator::Util qw(E data_checksum data_section data_type is_type json_pointer prefix_errors schema_type); -use List::Util 'uniq'; -use Mojo::File 'path'; +use JSON::Validator::Store; +use JSON::Validator::Util qw(E data_checksum data_type is_type json_pointer prefix_errors schema_type); +use List::Util qw(uniq); +use Mojo::File qw(path); use Mojo::JSON qw(false true); use Mojo::URL; -use Mojo::Util qw(url_unescape sha1_sum); +use Mojo::Util qw(sha1_sum); use Scalar::Util qw(blessed refaddr); -use constant CASE_TOLERANT => File::Spec->case_tolerant; -use constant DEBUG => $ENV{JSON_VALIDATOR_DEBUG} || 0; use constant RECURSION_LIMIT => $ENV{JSON_VALIDATOR_RECURSION_LIMIT} || 100; -our $VERSION = '4.09'; +our $VERSION = '4.10'; our @EXPORT_OK = qw(joi validate_json); our %SCHEMAS = ( - 'http://json-schema.org/draft-04/schema#' => '+Draft4', - 'http://json-schema.org/draft-06/schema#' => '+Draft6', - 'http://json-schema.org/draft-07/schema#' => '+Draft7', + 'http://json-schema.org/draft-04/schema#' => '+Draft4', + 'http://json-schema.org/draft-06/schema#' => '+Draft6', + 'http://json-schema.org/draft-07/schema#' => '+Draft7', + 'https://json-schema.org/draft/2019-09/schema' => '+Draft201909', ); -my $BUNDLED_CACHE_DIR = path(path(__FILE__)->dirname, qw(Validator cache)); -my $HTTP_SCHEME_RE = qr{^https?:}; +has formats => sub { shift->_build_formats }; +has recursive_data_protection => 1; -has cache_paths => sub { - return [split(/:/, $ENV{JSON_VALIDATOR_CACHE_PATH} || ''), $BUNDLED_CACHE_DIR]; +has store => sub { + my $self = shift; + my %attrs; + $attrs{$_} = delete $self->{$_} for grep { $self->{$_} } qw(cache_paths ua); + return JSON::Validator::Store->new(%attrs); }; -has formats => sub { shift->_build_formats }; - -has recursive_data_protection => 1; +# store proxy attributes +for my $method (qw(cache_paths ua)) { + Mojo::Util::monkey_patch(__PACKAGE__, $method => sub { shift->store->$method(@_) }); +} sub version { my $self = shift; @@ -47,14 +49,6 @@ $self; } -has ua => sub { - require Mojo::UserAgent; - my $ua = Mojo::UserAgent->new; - $ua->proxy->detect; - $ua->max_redirects(3); - $ua; -}; - sub bundle { my ($self, $args) = @_; my $cloner; @@ -145,6 +139,7 @@ sub joi { Mojo::Util::deprecated('JSON::Validator::joi() is replaced by JSON::Validator::Joi::joi().'); + require JSON::Validator::Joi; return JSON::Validator::Joi->new unless @_; my ($data, $joi) = @_; return $joi->validate($data, $joi); @@ -284,7 +279,7 @@ if ($topic->{$id_key} and !ref $topic->{$id_key}) { my $id = Mojo::URL->new($topic->{$id_key}); $id = $id->to_abs($base_url) unless $id->is_abs; - $self->_store($id->to_string => $topic); + $self->store->add($id => $topic); $base_url = $id; } @@ -312,87 +307,22 @@ sub _id_key { ($_[0]->{version} || 4) < 7 ? 'id' : '$id' } -sub _load_schema { - my ($self, $url) = @_; - - my $cached; - return $cached, $url if $cached = $self->_store($url); - - if ($url =~ m!^https?://!) { - warn "[JSON::Validator] Loading schema from URL $url\n" if DEBUG; - return $self->_load_schema_from_url(Mojo::URL->new($url)->fragment(undef)), "$url"; - } - - if ($url =~ m!^data://([^/]*)/(.*)!) { - my ($class, $file) = ($1, $2); - my $text = data_section $class, $file, {confess => 1, encoding => 'UTF-8'}; - return $self->_load_schema_from_text(\$text), "$url"; - } - - if ($url =~ m!^\s*[\[\{]!) { - warn "[JSON::Validator] Loading schema from string.\n" if DEBUG; - return $self->_load_schema_from_text(\$url), ''; - } - - my $file = $url; - $file =~ s!^file://!!; - $file =~ s!#$!!; - $file = path(split '/', url_unescape $file); - if (-e $file) { - $file = $file->realpath; - warn "[JSON::Validator] Loading schema from file: $file\n" if DEBUG; - $url = Mojo::URL->new->scheme('file')->host('')->path(CASE_TOLERANT ? lc $file : "$file"); - return $cached, $url if $cached = $self->_store($url); - return $self->_load_schema_from_text(\$file->slurp), $url; - } - elsif ($url =~ m!^/! and $self->ua->server->app) { - warn "[JSON::Validator] Loading schema from URL $url\n" if DEBUG; - return $self->_load_schema_from_url(Mojo::URL->new($url)->fragment(undef)), "$url"; - } - - confess "Unable to load schema '$url' ($file)"; -} - -sub _load_schema_from_text { - my ($self, $text) = @_; - return $$text =~ /^\s*\{/s ? Mojo::JSON::decode_json($$text) : JSON::Validator::Util::_yaml_load($$text); -} - -sub _load_schema_from_url { - my ($self, $url) = @_; - my $cache_path = $self->cache_paths->[0]; - my $cache_file = Mojo::Util::md5_sum("$url"); - - for (@{$self->cache_paths}) { - my $path = path $_, $cache_file; - warn "[JSON::Validator] Looking for cached spec $path ($url)\n" if DEBUG; - next unless -r $path; - return $self->_load_schema_from_text(\$path->slurp); - } - - my $tx = $self->ua->get($url); - my $err = $tx->error && $tx->error->{message}; - confess "GET $url == $err" if DEBUG and $err; - die "[JSON::Validator] GET $url == $err" if $err; - - if ($cache_path and ($cache_path ne $BUNDLED_CACHE_DIR or $ENV{JSON_VALIDATOR_CACHE_ANYWAYS}) and -w $cache_path) { - $cache_file = path $cache_path, $cache_file; - warn "[JSON::Validator] Caching $url to $cache_file\n" unless $ENV{HARNESS_ACTIVE}; - $cache_file->spurt($tx->res->body); - } - - return $self->_load_schema_from_text(\$tx->res->body); -} - sub _new_schema { - my ($self, $schema, %attrs) = @_; - return $schema if blessed $schema and $schema->can('specification'); + my ($self, $source, %attrs) = @_; + return $source if blessed $source and $source->can('specification'); # Compat with load_and_validate_schema() $attrs{specification} = delete $attrs{schema} if $attrs{schema}; - if (!$attrs{specification} and is_type $schema, 'HASH') { - $attrs{specification} = $schema->{'$schema'} if $schema->{'$schema'}; + my $loadable + = (blessed $source && ($source->can('scheme') || $source->isa('Mojo::File'))) + || -f $source + || (!ref $source && $source =~ /^\w/); + + my $store = $self->store; + my $schema = $loadable ? $store->get($store->load($source)) : $source; + if (!$attrs{specification} and is_type $schema, 'HASH' and $schema->{'$schema'}) { + $attrs{specification} = $schema->{'$schema'}; } if (!$attrs{specification} and $self->{version}) { $attrs{specification} = sprintf 'http://json-schema.org/draft-%02s/schema#', $self->{version}; @@ -400,11 +330,9 @@ $attrs{formats} ||= $self->{formats} if $self->{formats}; $attrs{version} ||= $self->{version} if $self->{version}; - $attrs{schemas} ||= $self->{schemas} ||= {}; - $attrs{$_} = $self->$_ for qw(cache_paths ua); + $attrs{store} = $store; - my $schema_obj = $self->_schema_class($attrs{specification} || $schema)->new($schema, %attrs); - return $schema_obj; + return $self->_schema_class($attrs{specification} || $schema)->new($source, %attrs); } sub _node { @@ -447,23 +375,24 @@ my ($self, $schema, $nested) = @_; return $schema if is_type $schema, 'BOOL'; - my ($id_key, $id, $resolved) = ($self->_id_key); + my ($id_key, $id, $cached_id, $resolved) = ($self->_id_key); if (ref $schema eq 'HASH') { - $id = $schema->{$id_key} // ''; - $resolved = $self->_store($id) // $schema; + $id = $schema->{$id_key} // ''; + $cached_id = $self->store->exists($id); + $resolved = $cached_id ? $self->store->get($cached_id) : $schema; } else { - ($resolved, $id) = $self->_load_schema($schema); - $id = $resolved->{$id_key} if is_type($resolved, 'HASH') and $resolved->{$id_key}; + $cached_id = $self->store->exists($id); + $id = $cached_id // $self->store->load($schema); + $resolved = $self->store->get($id); + $id = $resolved->{$id_key} if is_type($resolved, 'HASH') and $resolved->{$id_key}; } + $cached_id //= ''; $id = Mojo::URL->new("$id"); $self->_register_root_schema($id => $resolved) if !$nested and "$id"; - - unless ($self->_store($id)) { - $self->_store($id => $resolved) if "$id"; - $self->_find_and_resolve_refs($id => $resolved); - } + $self->store->add($id => $resolved) if "$id" and "$id" ne $cached_id; + $self->_find_and_resolve_refs($id => $resolved) unless $cached_id; return $resolved; } @@ -477,8 +406,8 @@ my $other; $fqn = $fqn->to_abs($base_url) if "$base_url"; - $other //= $self->_store($fqn); - $other //= $self->_store($fqn->clone->fragment(undef)); + $other //= $self->store->get($fqn); + $other //= $self->store->get($fqn->clone->fragment(undef)); $other //= $self->_resolve($fqn->clone->fragment(undef), 1) if $fqn->is_abs && $fqn ne $base_url; $other //= $schema; @@ -513,13 +442,6 @@ return $package; } -sub _store { - my ($self, $id, $schema) = @_; - $id =~ s!(.)#$!$1!; - return $self->{schemas}{$id} unless defined $schema; - return $self->{schemas}{$id} = $schema; -} - sub _validate { my ($self, $data, $path, $schema) = @_; $schema = $self->_ref_to_schema($schema); @@ -609,7 +531,7 @@ push @errors, @e; } - # favour a non-type error from one of the rules + # favor a non-type error from one of the rules if (my @e = grep { $_->details->[1] ne 'type' or $_->path ne ($path || '/') } @errors) { return @e; } @@ -1134,16 +1056,7 @@ =head2 cache_paths - my $jv = $jv->cache_paths(\@paths); - my $array_ref = $jv->cache_paths; - -A list of directories to where cached specifications are stored. Defaults to -C<JSON_VALIDATOR_CACHE_PATH> environment variable and the specs that is bundled -with this distribution. - -C<JSON_VALIDATOR_CACHE_PATH> can be a list of directories, each separated by ":". - -See L</Bundled specifications> for more details. +Proxy attribtue for L<JSON::Validator::Store/cache_paths>. =head2 formats @@ -1177,14 +1090,7 @@ =head2 ua - my $ua = $jv->ua; - my $jv = $jv->ua(Mojo::UserAgent->new); - -Holds a L<Mojo::UserAgent> object, used by L</schema> to load a JSON schema -from remote location. - -The default L<Mojo::UserAgent> will detect proxy settings and have -L<Mojo::UserAgent/max_redirects> set to 3. +Proxy attribtue for L<JSON::Validator::Store/ua>. =head2 version diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/JSON-Validator-4.09/t/bundle.t new/JSON-Validator-4.10/t/bundle.t --- old/JSON-Validator-4.09/t/bundle.t 2020-10-09 00:10:54.000000000 +0200 +++ new/JSON-Validator-4.10/t/bundle.t 2020-10-13 01:13:59.000000000 +0200 @@ -8,18 +8,11 @@ my $jv = JSON::Validator->new; my $bundled; -{ - note 'bundle files'; - local $ENV{JSON_VALIDATOR_CACHE_ANYWAYS} = 1; - $jv->_load_schema_from_url("http://json-schema.org/draft-04/schema"); - $jv->_load_schema_from_url("http://json-schema.org/draft-06/schema"); - $jv->_load_schema_from_url("http://json-schema.org/draft-07/schema"); -} - my $schema = JSON::Validator::Schema::Draft7->new({ definitions => {name => {type => 'string'}}, surname => {'$ref' => '#/definitions/name'}, }); + is $schema->bundle({replace => 1})->data->{surname}{type}, 'string', "schema->bundle"; note 'Run multiple times to make sure _reset() works'; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/JSON-Validator-4.09/t/draft2019-09.t new/JSON-Validator-4.10/t/draft2019-09.t --- old/JSON-Validator-4.09/t/draft2019-09.t 2020-10-12 00:56:10.000000000 +0200 +++ new/JSON-Validator-4.10/t/draft2019-09.t 2020-10-13 03:47:15.000000000 +0200 @@ -20,12 +20,21 @@ is $schema->data->{type}, 'integer', 'foo anchor type'; note 'recursiveRef, without recursiveAnchor'; -$schema->data('data://main/tree.json')->resolve; -$schema->data('data://main/recursiveRef.json')->resolve; -is $schema->data->{type}, 'object', 'recursiveRef type'; -is $schema->data->{properties}{data}, true, 'recursiveRef properties data'; -is $schema->data->{properties}{children}{items}{type}, 'object', 'recursiveRef properties data items'; -is $schema->data->{properties}{children}{items}{properties}{children}{items}{type}, 'object', 'recursive'; +my $jv = JSON::Validator->new->schema('data://main/tree.json'); +$jv->schema('data://main/recursiveRef.json'); +isa_ok $jv->schema, 'JSON::Validator::Schema::Draft201909'; +is $jv->schema->data->{type}, 'object', 'recursiveRef type'; +is $jv->schema->data->{properties}{data}, true, 'recursiveRef properties data'; +is $jv->schema->data->{properties}{children}{items}{type}, 'object', 'recursiveRef properties data items'; +is $jv->schema->data->{properties}{children}{items}{properties}{children}{items}{type}, 'object', 'recursive'; +is_deeply [sort keys %{$jv->store->schemas}], + [qw(data://main/recursiveRef.json data://main/tree.json urn:recursiveRef urn:tree)], 'schemas in the store'; + +{ + no warnings 'redefine'; + local *JSON::Validator::_load_from_data = sub { die 'not cached' }; + ok eval { JSON::Validator->new->schema('data://main/tree.json') }, 'cached' or diag $@; +} done_testing; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/JSON-Validator-4.09/t/jv-boolean.t new/JSON-Validator-4.10/t/jv-boolean.t --- old/JSON-Validator-4.09/t/jv-boolean.t 2020-10-09 00:20:23.000000000 +0200 +++ new/JSON-Validator-4.10/t/jv-boolean.t 2020-10-13 02:12:33.000000000 +0200 @@ -33,7 +33,7 @@ validate_ok false, $bool_constant_true, E('/', q{Does not match const: true.}); note 'boolean objects'; -my $data = jv->_load_schema_from_text(\"---\nv: true\n"); +my $data = jv->store->get(jv->store->load(\"---\nv: true\n")); isa_ok($data->{v}, 'JSON::PP::Boolean'); validate_ok $data, $schema; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/JSON-Validator-4.09/t/load-data.t new/JSON-Validator-4.10/t/load-data.t --- old/JSON-Validator-4.09/t/load-data.t 2020-10-09 00:22:59.000000000 +0200 +++ new/JSON-Validator-4.10/t/load-data.t 2020-10-13 00:15:59.000000000 +0200 @@ -31,7 +31,7 @@ sub validate { $jv->schema($_[1])->validate($_[2]) } package main; -is_deeply [sort keys %{$jv->{schemas}}], [qw(data:///spec.json data://main/spec.json)], 'schemas in store'; +is_deeply [sort keys %{$jv->store->schemas}], [qw(data:///spec.json data://main/spec.json)], 'schemas in store'; done_testing; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/JSON-Validator-4.09/t/load-file.t new/JSON-Validator-4.10/t/load-file.t --- old/JSON-Validator-4.09/t/load-file.t 2020-10-12 01:05:18.000000000 +0200 +++ new/JSON-Validator-4.10/t/load-file.t 2020-10-13 00:10:28.000000000 +0200 @@ -12,10 +12,10 @@ isa_ok $jv->schema, 'JSON::Validator::Schema'; is $jv->schema->get('/title'), 'Example Schema', 'got example schema'; is $jv->schema->id, $id, 'schema id'; -is_deeply [sort keys %{$jv->{schemas}}], [$jv->schema->id], 'schemas in store'; +is_deeply [sort keys %{$jv->store->schemas}], [$jv->schema->id], 'schemas in store'; ok eval { $jv->schema($spec->to_string) }, 'loaded from file:// again' or diag $@; is $jv->schema->id, $id, 'schema id again'; -is_deeply [sort keys %{$jv->{schemas}}], [$jv->schema->id], 'schemas in store again'; +is_deeply [sort keys %{$jv->store->schemas}], [$jv->schema->id], 'schemas in store again'; done_testing; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/JSON-Validator-4.09/t/load-from-app.t new/JSON-Validator-4.10/t/load-from-app.t --- old/JSON-Validator-4.09/t/load-from-app.t 2020-10-09 00:22:59.000000000 +0200 +++ new/JSON-Validator-4.10/t/load-from-app.t 2020-10-13 02:12:33.000000000 +0200 @@ -7,18 +7,28 @@ $jv->ua->server->app(Mojolicious->new); $jv->ua->server->app->routes->get( '/spec' => sub { - shift->render(json => {'$ref' => 'http://swagger.io/v2/schema.json'}); + my $c = shift; + die 'not cached' if $c->stash('from_cache'); + $c->render(json => {'$ref' => 'http://swagger.io/v2/schema.json'}); } ); -# Some CPAN testers says: [JSON::Validator] GET http://127.0.0.1:61594/api == Service Unavailable at JSON/Validator.pm +# Some CPAN testers says "Service Unavailable" eval { $jv->schema('/spec') }; plan skip_all => $@ if $@ =~ /\sGET\s/i; +is $jv->store->ua, $jv->ua, 'shared ua'; is $@, '', 'loaded schema from app'; is $jv->get('/properties/swagger/enum/0'), '2.0', 'loaded schema structure'; -is_deeply [sort keys %{$jv->{schemas}}], +is_deeply [sort keys %{$jv->store->schemas}], ['/spec', 'http://json-schema.org/draft-04/schema', 'http://swagger.io/v2/schema.json'], 'schemas in store'; +$jv->ua->server->app->defaults(from_cache => 1); +ok $jv->schema('/spec'), 'loaded from cache'; + +$jv->store->schemas({}); +eval { $jv->schema('/spec') }; +like $@, qr{Internal Server Error}, 'cache cleared'; + done_testing; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/JSON-Validator-4.09/t/load-http.t new/JSON-Validator-4.10/t/load-http.t --- old/JSON-Validator-4.09/t/load-http.t 2020-10-09 00:22:59.000000000 +0200 +++ new/JSON-Validator-4.10/t/load-http.t 2020-10-13 00:10:28.000000000 +0200 @@ -12,7 +12,7 @@ like $jv->schema->get('/title'), qr{swagger}i, 'got swagger spec'; ok $jv->schema->get('/patternProperties/^x-/description'), 'resolved vendorExtension $ref'; -is_deeply [sort keys %{$jv->{schemas}}], +is_deeply [sort keys %{$jv->store->schemas}], ['http://json-schema.org/draft-04/schema', 'http://swagger.io/v2/schema.json'], 'schemas in store'; done_testing; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/JSON-Validator-4.09/t/load-json.t new/JSON-Validator-4.10/t/load-json.t --- old/JSON-Validator-4.09/t/load-json.t 2020-10-09 00:22:59.000000000 +0200 +++ new/JSON-Validator-4.10/t/load-json.t 2020-10-13 01:00:34.000000000 +0200 @@ -22,6 +22,6 @@ is(eval { JSON::Validator->new->schema('http://swagger.io/v2/schema.json'); 42 }, 42, 'loaded from cache') or diag $@; like $jv->schema->id, qr{^file:.*person\.json}, 'schema id'; -is_deeply [sort keys %{$jv->{schemas}}], [$jv->schema->id], 'schemas in store'; +is_deeply [sort keys %{$jv->store->schemas}], [$jv->schema->id], 'schemas in store'; done_testing; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/JSON-Validator-4.09/t/predictable-errors.t new/JSON-Validator-4.10/t/predictable-errors.t --- old/JSON-Validator-4.09/t/predictable-errors.t 2020-10-05 23:31:23.000000000 +0200 +++ new/JSON-Validator-4.10/t/predictable-errors.t 2020-10-12 23:33:35.000000000 +0200 @@ -11,15 +11,11 @@ # so looping around like this will execute the test with all kinds of # different internal ordering for (1 .. 20) { - $jv->schema(my $schema_text - = '{ "type": "object", "properties": { "ant": { "type": "string" }, "bat": { "type": "array" }, "cat": { "type": "object" }, "dog": { "type": "integer" } } }' - ); - my @errors = $jv->validate($broken_data); - is_deeply([map { $_->path } @errors], [qw(/ant /bat /cat /dog)], "got errors in expected order"); - if (!$num_errors) { # only run this test once - $num_errors = $jv->validate($broken_data); - is($num_errors, 4, "in scalar context got the right number of errors"); - } + my $schema_text + = '{"type":"object","properties":{"ant":{"type":"string"},"bat":{"type":"array"},"cat":{"type":"object"},"dog":{"type":"integer"}}}'; + $jv->schema($schema_text); + is_deeply [map { $_->path } $jv->validate($broken_data)], [qw(/ant /bat /cat /dog)], 'got errors in expected order'; + is scalar $jv->validate($broken_data), 4, 'in scalar context got the right number of errors'; } done_testing;