File Coverage

blib/lib/JSON/Validator/Error.pm
Criterion Covered Total %
statement 15 16 93.7
branch 6 6 100.0
condition 2 2 100.0
subroutine 5 6 83.3
pod 2 3 66.6
total 30 33 90.9


line stmt bran cond sub pod time code
1             package JSON::Validator::Error;
2 49     49   322 use Mojo::Base -base;
  49         92  
  49         283  
3              
4 49     49   8835 use overload q("") => \&to_string, bool => sub {1}, fallback => 1;
  49     0   96  
  49         517  
  0         0  
5              
6             our $MESSAGES = {
7             allOf => {type => '/allOf Expected %3 - got %4.'},
8             anyOf => {type => '/anyOf Expected %3 - got %4.'},
9             array => {
10             additionalItems => 'Invalid number of items: %3/%4.',
11             maxItems => 'Too many items: %3/%4.',
12             minItems => 'Not enough items: %3/%4.',
13             uniqueItems => 'Unique items required.',
14             },
15             const => {const => 'Does not match const: %3.'},
16             enum => {enum => 'Not in enum list: %3.'},
17             integer => {
18             ex_maximum => '%3 >= maximum(%4)',
19             ex_minimum => '%3 <= minimum(%4)',
20             maximum => '%3 > maximum(%4)',
21             minimum => '%3 < minimum(%4)',
22             multipleOf => 'Not multiple of %3.',
23             },
24             not => {not => 'Should not match.'},
25             null => {null => 'Not null.'},
26             number => {
27             ex_maximum => '%3 >= maximum(%4)',
28             ex_minimum => '%3 <= minimum(%4)',
29             maximum => '%3 > maximum(%4)',
30             minimum => '%3 < minimum(%4)',
31             multipleOf => 'Not multiple of %3.',
32             },
33             object => {
34             additionalProperties => 'Properties not allowed: %3.',
35             maxProperties => 'Too many properties: %3/%4.',
36             minProperties => 'Not enough properties: %3/%4.',
37             required => 'Missing property.',
38             dependencies => 'Missing property. Dependee: %3.',
39             },
40             oneOf => {
41             all_rules_match => 'All of the oneOf rules match.',
42             n_rules_match => 'oneOf rules %3 match.',
43             type => '/oneOf Expected %3 - got %4.',
44             },
45             string => {
46             pattern => 'String does not match %3.',
47             maxLength => 'String is too long: %3/%4.',
48             minLength => 'String is too short: %3/%4.',
49             }
50             };
51              
52             has details => sub { [qw(generic generic)] };
53              
54             has message => sub {
55             my $self = shift;
56             my $details = $self->details;
57             my $message;
58              
59             if (($details->[0] || '') eq 'format') {
60             $message = '%3';
61             }
62             elsif (($details->[1] || '') eq 'type' and @$details == 3) {
63             $message = 'Expected %1 - got %3.';
64             }
65             elsif (my $group = $MESSAGES->{$details->[0]}) {
66             $message = $group->{$details->[1] || 'default'};
67             }
68              
69             return join ' ', Failed => @$details unless defined $message;
70              
71             $message =~ s!\%(\d)\b!{$details->[$1 - 1] // ''}!ge;
72             return $message;
73             };
74              
75             has path => '/';
76              
77             sub new {
78 703     703 1 2244 my $class = shift;
79              
80             # Constructed with attributes
81 703 100       1930 return $class->SUPER::new($_[0]) if ref $_[0] eq 'HASH';
82              
83             # Constructed with ($path, ...)
84 702         2210 my $self = $class->SUPER::new;
85 702   100     6902 $self->{path} = shift || '/';
86              
87             # Constructed with ($path, $message)
88 702 100       2261 $self->message(shift) unless ref $_[0];
89              
90             # Constructed with ($path, \@details)
91 702 100       3626 $self->details(shift) if ref $_[0];
92              
93 702         4777 return $self;
94             }
95              
96 323     323 1 4403 sub to_string { sprintf '%s: %s', $_[0]->path, $_[0]->message }
97 360     360 0 3827 sub TO_JSON { {message => $_[0]->message, path => $_[0]->path} }
98              
99             1;
100              
101             =encoding utf8
102              
103             =head1 NAME
104              
105             JSON::Validator::Error - JSON::Validator error object
106              
107             =head1 SYNOPSIS
108              
109             use JSON::Validator::Error;
110             my $err = JSON::Validator::Error->new($path, $message);
111              
112             =head1 DESCRIPTION
113              
114             L is a class representing validation errors from
115             L.
116              
117             =head1 ATTRIBUTES
118              
119             =head2 details
120              
121             my $error = $error->details(["generic", "generic"]);
122             my $error = $error->details([qw(array type object)]);
123             my $error = $error->details([qw(format date-time Invalid)]);
124             my $array_ref = $error->details;
125              
126             Details about the error:
127              
128             =over 2
129              
130             =item 1.
131              
132             Often the category of tests that was run. Example values: allOf, anyOf, array,
133             const, enum, format, integer, not, null, number, object, oneOf and string.
134              
135             =item 2.
136              
137             Often the test that failed. Example values: additionalItems,
138             additionalProperties, const, enum, maxItems, maxLength, maxProperties, maximum,
139             minItems, minLength. minProperties, minimum, multipleOf, not, null, pattern,
140             required, type and uniqueItems,
141              
142             =item 3.
143              
144             The rest of the list contains parameters for the test that failed. It can be a
145             plain human-readable string or numbers indicating things such as max/min
146             values.
147              
148             =back
149              
150             =head2 message
151              
152             my $str = $error->message;
153              
154             A human readable description of the error. Defaults to being being constructed
155             from L. See the C<$MESSAGES> variable in the source code for more
156             details.
157              
158             As an EXPERIMENTAL hack you can localize C<$JSON::Validator::Error::MESSAGES>
159             to get i18n support. Example:
160              
161             sub validate_i18n {
162             local $JSON::Validator::Error::MESSAGES = {
163             allOf => {type => '/allOf Forventet %3 - fikk %4.'},
164             };
165              
166             my @error_norwegian = $jv->validate({age => 42});
167             }
168              
169             Note that the error messages might contain a mix of English and the local
170             language. Run some tests to see how it looks.
171              
172             =head2 path
173              
174             my $str = $error->path;
175              
176             A JSON pointer to where the error occurred. Defaults to "/".
177              
178             =head1 METHODS
179              
180             =head2 new
181              
182             my $error = JSON::Validator::Error->new(\%attributes);
183             my $error = JSON::Validator::Error->new($path, \@details);
184             my $error = JSON::Validator::Error->new($path, \@details);
185              
186             Object constructor.
187              
188             =head2 to_string
189              
190             my $str = $error->to_string;
191              
192             Returns the "path" and "message" part as a string: "$path: $message".
193              
194             =head1 OPERATORS
195              
196             L overloads the following operators:
197              
198             =head2 bool
199              
200             my $bool = !!$error;
201              
202             Always true.
203              
204             =head2 stringify
205              
206             my $str = "$error";
207              
208             Alias for L.
209              
210             =head1 SEE ALSO
211              
212             L.
213              
214             =cut