File Coverage

blib/lib/JSON/Schema/Modern/Annotation.pm
Criterion Covered Total %
statement 48 54 88.8
branch 1 4 25.0
condition n/a
subroutine 16 17 94.1
pod 2 2 100.0
total 67 77 87.0


line stmt bran cond sub pod time code
1 36     36   710 use strict;
  36         85  
  36         1163  
2 36     36   206 use warnings;
  36         82  
  36         1878  
3             package JSON::Schema::Modern::Annotation;
4             # vim: set ts=8 sts=2 sw=2 tw=100 et :
5             # ABSTRACT: Contains a single annotation from a JSON Schema evaluation
6              
7             our $VERSION = '0.572';
8              
9 36     36   622 use 5.020;
  36         134  
10 36     36   213 use Moo;
  36         95  
  36         233  
11 36     36   13066 use strictures 2;
  36         260  
  36         1419  
12 36     36   6666 use stable 0.031 'postderef';
  36         1432  
  36         303  
13 36     36   4877 use experimental 'signatures';
  36         105  
  36         151  
14 36     36   3042 use if "$]" >= 5.022, experimental => 're_strict';
  36         76  
  36         361  
15 36     36   3372 no if "$]" >= 5.031009, feature => 'indirect';
  36         114  
  36         244  
16 36     36   1759 no if "$]" >= 5.033001, feature => 'multidimensional';
  36         85  
  36         210  
17 36     36   1838 no if "$]" >= 5.033006, feature => 'bareword_filehandles';
  36         99  
  36         218  
18 36     36   1349 use Safe::Isa;
  36         130  
  36         5449  
19 36     36   257 use MooX::TypeTiny;
  36         88  
  36         288  
20 36     36   28816 use Types::Standard qw(Str InstanceOf Bool);
  36         88  
  36         267  
21 36     36   63396 use namespace::clean;
  36         98  
  36         356  
22              
23             has [qw(
24             keyword
25             instance_location
26             keyword_location
27             )] => (
28             is => 'ro',
29             isa => Str,
30             required => 1,
31             );
32              
33             has absolute_keyword_location => (
34             is => 'ro',
35             isa => InstanceOf['Mojo::URL'],
36             coerce => sub { $_[0]->$_isa('Mojo::URL') ? $_[0] : Mojo::URL->new($_[0]) },
37             );
38              
39             # https://json-schema.org/draft/2019-09/json-schema-core.html#rfc.section.7.7.1
40             has annotation => (
41             is => 'ro',
42             required => 1,
43             );
44              
45             has unknown => (
46             is => 'ro',
47             isa => Bool,
48             default => 0,
49             );
50              
51             around BUILDARGS => sub ($orig, $class, @args) {
52             my $args = $class->$orig(@args);
53              
54             if (my $uri = delete $args->{_uri}) {
55             # as if we did canonical_uri(..)->to_abs($state->{effective_base_uri} in A(..)
56             $uri = $uri->[0]->to_abs($uri->[1]);
57             undef $uri if $uri eq '' and $args->{keyword_location} eq ''
58             or ($uri->fragment // '') eq $args->{keyword_location} and $uri->clone->fragment(undef) eq '';
59             $args->{absolute_keyword_location} = $uri if defined $uri;
60             }
61              
62             return $args;
63             };
64              
65 33     33 1 7233 sub TO_JSON ($self) {
  33         49  
  33         55  
66             return +{
67             # note that locations are JSON pointers, not uri fragments!
68 33 50       537 instanceLocation => $self->instance_location,
69             keywordLocation => $self->keyword_location,
70             !defined($self->absolute_keyword_location) ? ()
71             : ( absoluteKeywordLocation => $self->absolute_keyword_location->to_string ),
72             annotation => $self->annotation,
73             };
74             }
75              
76 0     0 1   sub dump ($self) {
  0            
  0            
77 0           my $encoder = JSON::MaybeXS->new(utf8 => 0, convert_blessed => 1, canonical => 1, indent => 1, space_after => 1);
78 0 0         $encoder->indent_length(2) if $encoder->can('indent_length');
79 0           $encoder->encode($self);
80             }
81              
82             1;
83              
84             __END__
85              
86             =pod
87              
88             =encoding UTF-8
89              
90             =for stopwords schema fragmentless
91              
92             =head1 NAME
93              
94             JSON::Schema::Modern::Annotation - Contains a single annotation from a JSON Schema evaluation
95              
96             =head1 VERSION
97              
98             version 0.572
99              
100             =head1 SYNOPSIS
101              
102             use JSON::Schema::Modern;
103             my $js = JSON::Schema::Modern->new;
104             my $result = $js->evaluate($data, $schema);
105             my @annotations = $result->annotations;
106              
107             my $value = $annotations[0]->annotation;
108             my $instance_location = $annotations[0]->instance_location;
109              
110             my $annotations_encoded = encode_json(\@annotations);
111              
112             =head1 DESCRIPTION
113              
114             An instance of this class holds one annotation from evaluating a JSON Schema with
115             L<JSON::Schema::Modern>.
116              
117             =head1 ATTRIBUTES
118              
119             =head2 keyword
120              
121             The keyword that produced the annotation.
122              
123             =head2 instance_location
124              
125             The path in the instance where the annotation was produced; encoded as per the JSON Pointer
126             specification (L<RFC 6901|https://datatracker.ietf.org/doc/html/rfc6901>).
127              
128             =head2 keyword_location
129              
130             The schema path taken during evaluation to arrive at the annotation; encoded as per the JSON Pointer
131             specification (L<RFC 6901|https://datatracker.ietf.org/doc/html/rfc6901>).
132              
133             =head2 absolute_keyword_location
134              
135             The canonical URI or URI reference of the location in the schema where the error occurred; not
136             defined, if there is no base URI for the schema and no C<$ref> was followed. Note that this is not
137             actually fragmentless URI in most cases, as the indicated error will occur at a path
138             below the position where the most recent identifier had been declared in the schema. Further, if the
139             schema never declared an absolute base URI (containing a scheme), this URI won't be absolute either.
140              
141             =head2 unknown
142              
143             A boolean flag, indicating whether the keyword is a known vocabulary keyword or unknown.
144              
145             =head2 annotation
146              
147             The actual annotation value (which may or may not be a string).
148              
149             =head1 METHODS
150              
151             =for Pod::Coverage BUILDARGS
152              
153             =head2 TO_JSON
154              
155             Returns a data structure suitable for serialization. Corresponds to one output unit as specified in
156             L<https://json-schema.org/draft/2019-09/json-schema-core.html#rfc.section.10.4.2> and
157             L<https://json-schema.org/draft/2019-09/output/schema>, except that C<instanceLocation> and
158             C<keywordLocation> are JSON pointers, B<not> URI fragments. (See the
159             C<strict_basic> L<JSON::Schema::Modern/output_format>
160             if the distinction is important to you.)
161              
162             =head2 dump
163              
164             Returns a JSON string representing the error object, according to
165             the L<specification|https://json-schema.org/draft/2019-09/json-schema-core.html#rfc.section.10>.
166              
167             =for stopwords OpenAPI
168              
169             =head1 SUPPORT
170              
171             Bugs may be submitted through L<https://github.com/karenetheridge/JSON-Schema-Modern/issues>.
172              
173             I am also usually active on irc, as 'ether' at C<irc.perl.org> and C<irc.libera.chat>.
174              
175             You can also find me on the L<JSON Schema Slack server|https://json-schema.slack.com> and L<OpenAPI Slack
176             server|https://open-api.slack.com>, which are also great resources for finding help.
177              
178             =head1 AUTHOR
179              
180             Karen Etheridge <ether@cpan.org>
181              
182             =head1 COPYRIGHT AND LICENCE
183              
184             This software is copyright (c) 2020 by Karen Etheridge.
185              
186             This is free software; you can redistribute it and/or modify it under
187             the same terms as the Perl 5 programming language system itself.
188              
189             =cut