File Coverage

blib/lib/YAML/PP/Schema/JSON.pm
Criterion Covered Total %
statement 87 87 100.0
branch 18 20 90.0
condition 4 5 80.0
subroutine 15 15 100.0
pod 6 6 100.0
total 130 133 97.7


line stmt bran cond sub pod time code
1 51     51   142798 use strict;
  51         73  
  51         2929  
2 51     51   186 use warnings;
  51         73  
  51         3071  
3             package YAML::PP::Schema::JSON;
4              
5             our $VERSION = 'v0.40.1'; # TRIAL VERSION
6              
7 51     51   208 use base 'Exporter';
  51         64  
  51         5889  
8             our @EXPORT_OK = qw/
9             represent_int represent_float represent_literal represent_bool
10             represent_undef
11             /;
12              
13 51     51   235 use B;
  51         77  
  51         1155  
14 51     51   177 use Carp qw/ croak /;
  51         97  
  51         2566  
15              
16 51     51   1343 use YAML::PP::Common qw/ YAML_PLAIN_SCALAR_STYLE YAML_SINGLE_QUOTED_SCALAR_STYLE /;
  51         73  
  51         48066  
17              
18             my $RE_INT = qr{^(-?(?:0|[1-9][0-9]*))$};
19             my $RE_FLOAT = qr{^(-?(?:0|[1-9][0-9]*)(?:\.[0-9]*)?(?:[eE][+-]?[0-9]+)?)$};
20              
21 9703     9703   32521 sub _to_int { 0 + $_[2]->[0] }
22              
23             # DaTa++ && shmem++
24 76     76   727 sub _to_float { unpack F => pack F => $_[2]->[0] }
25              
26             sub register {
27 22     22 1 83 my ($self, %args) = @_;
28 22         32 my $schema = $args{schema};
29 22         32 my $options = $args{options};
30 22         31 my $empty_null = 0;
31 22         41 for my $opt (@$options) {
32 2 50       6 if ($opt eq 'empty=str') {
    100          
33             }
34             elsif ($opt eq 'empty=null') {
35 1         2 $empty_null = 1;
36             }
37             else {
38 1         205 croak "Invalid option for JSON Schema: '$opt'";
39             }
40             }
41              
42             $schema->add_resolver(
43 21         71 tag => 'tag:yaml.org,2002:null',
44             match => [ equals => null => undef ],
45             );
46 21 100       41 if ($empty_null) {
47 1         3 $schema->add_resolver(
48             tag => 'tag:yaml.org,2002:null',
49             match => [ equals => '' => undef ],
50             implicit => 1,
51             );
52             }
53             else {
54 20         66 $schema->add_resolver(
55             tag => 'tag:yaml.org,2002:str',
56             match => [ equals => '' => '' ],
57             implicit => 1,
58             );
59             }
60 21         70 $schema->add_resolver(
61             tag => 'tag:yaml.org,2002:bool',
62             match => [ equals => true => $schema->true ],
63             );
64 21         55 $schema->add_resolver(
65             tag => 'tag:yaml.org,2002:bool',
66             match => [ equals => false => $schema->false ],
67             );
68 21         66 $schema->add_resolver(
69             tag => 'tag:yaml.org,2002:int',
70             match => [ regex => $RE_INT => \&_to_int ],
71             );
72 21         59 $schema->add_resolver(
73             tag => 'tag:yaml.org,2002:float',
74             match => [ regex => $RE_FLOAT => \&_to_float ],
75             );
76             $schema->add_resolver(
77             tag => 'tag:yaml.org,2002:str',
78 21     338   98 match => [ all => sub { $_[1]->{value} } ],
  338         1111  
79             );
80              
81 21         68 $schema->add_representer(
82             undefined => \&represent_undef,
83             );
84              
85 21         47 my $int_flags = B::SVp_IOK;
86 21         28 my $float_flags = B::SVp_NOK;
87 21         47 $schema->add_representer(
88             flags => $int_flags,
89             code => \&represent_int,
90             );
91 21         77 my %special = ( (0+'nan').'' => '.nan', (0+'inf').'' => '.inf', (0-'inf').'' => '-.inf' );
92 21         63 $schema->add_representer(
93             flags => $float_flags,
94             code => \&represent_float,
95             );
96             $schema->add_representer(
97             equals => $_,
98             code => \&represent_literal,
99 21         55 ) for ("", qw/ true false null /);
100 21         530 $schema->add_representer(
101             regex => qr{$RE_INT|$RE_FLOAT},
102             code => \&represent_literal,
103             );
104              
105 21 50       46 if ($schema->bool_class) {
106 21         24 for my $class (@{ $schema->bool_class }) {
  21         37  
107 21 100       45 if ($class eq 'perl') {
108 19         40 $schema->add_representer(
109             bool => 1,
110             code => \&represent_bool,
111             );
112 19         30 next;
113             }
114             $schema->add_representer(
115 2         3 class_equals => $class,
116             code => \&represent_bool,
117             );
118             }
119             }
120              
121 21         71 return;
122             }
123              
124             sub represent_undef {
125 110     110 1 166 my ($rep, $node) = @_;
126 110         184 $node->{style} = YAML_PLAIN_SCALAR_STYLE;
127 110         157 $node->{data} = 'null';
128 110         291 return 1;
129             }
130              
131             sub represent_literal {
132 219     219 1 406 my ($rep, $node) = @_;
133 219   100     1143 $node->{style} ||= YAML_SINGLE_QUOTED_SCALAR_STYLE;
134 219         534 $node->{data} = "$node->{value}";
135 219         761 return 1;
136             }
137              
138              
139             sub represent_int {
140 386     386 1 610 my ($rep, $node) = @_;
141 386 100       1124 if (int($node->{value}) ne $node->{value}) {
142 7         20 return 0;
143             }
144 379         637 $node->{style} = YAML_PLAIN_SCALAR_STYLE;
145 379         674 $node->{data} = "$node->{value}";
146 379         1060 return 1;
147             }
148              
149             my %special = (
150             (0+'nan').'' => '.nan',
151             (0+'inf').'' => '.inf',
152             (0-'inf').'' => '-.inf'
153             );
154             sub represent_float {
155 131     131 1 177 my ($rep, $node) = @_;
156 131 100       644 if (exists $special{ $node->{value} }) {
157 48         104 $node->{style} = YAML_PLAIN_SCALAR_STYLE;
158 48         86 $node->{data} = $special{ $node->{value} };
159 48         148 return 1;
160             }
161 83 100       331 if (0.0 + $node->{value} ne $node->{value}) {
162 4         11 return 0;
163             }
164 79 100 66     355 if (int($node->{value}) eq $node->{value} and not $node->{value} =~ m/\./) {
165 35         63 $node->{value} .= '.0';
166             }
167 79         135 $node->{style} = YAML_PLAIN_SCALAR_STYLE;
168 79         157 $node->{data} = "$node->{value}";
169 79         218 return 1;
170             }
171              
172             sub represent_bool {
173 66     66 1 97 my ($rep, $node) = @_;
174 66 100       229 my $string = $node->{value} ? 'true' : 'false';
175 66         461 $node->{style} = YAML_PLAIN_SCALAR_STYLE;
176 66         83 @{ $node->{items} } = $string;
  66         174  
177 66         96 $node->{data} = $string;
178 66         177 return 1;
179             }
180              
181             1;
182              
183             __END__