File Coverage

blib/lib/JSON/Create/PP.pm
Criterion Covered Total %
statement 336 372 90.3
branch 148 172 86.0
condition 16 18 88.8
subroutine 56 58 96.5
pod 0 49 0.0
total 556 669 83.1


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             JSON::Create::PP - Pure-Perl version of JSON::Create
4              
5             =head1 DESCRIPTION
6              
7             This is a backup module for JSON::Create. JSON::Create is written
8             using Perl XS, but JSON::Create::PP offers the same functionality
9             without the XS.
10              
11             =head1 DEPENDENCIES
12              
13             =over
14              
15             =item L
16              
17             =item L
18              
19             This uses Carp to report errors.
20              
21             =item L
22              
23             Scalar::Util is used to distinguish strings from numbers, detect
24             objects, and break encapsulation.
25              
26             =item L
27              
28             This is used to handle conversion to and from character strings.
29              
30             =back
31              
32             =head1 BUGS
33              
34             Printing of floating point numbers cannot be made to work exactly like
35             the XS version.
36              
37             =cut
38              
39             package JSON::Create::PP;
40 23     23   11490 use parent Exporter;
  23         7751  
  23         128  
41             our @EXPORT_OK = qw/create_json create_json_strict json_escape/;
42             our %EXPORT_TAGS = (all => \@EXPORT_OK);
43 23     23   1897 use warnings;
  23         48  
  23         572  
44 23     23   115 use strict;
  23         39  
  23         471  
45 23     23   785 use utf8;
  23         49  
  23         149  
46 23     23   587 use Carp qw/croak carp confess cluck/;
  23         45  
  23         1453  
47 23     23   132 use Scalar::Util qw/looks_like_number blessed reftype/;
  23         45  
  23         1224  
48 23     23   11366 use Unicode::UTF8 qw/decode_utf8 valid_utf8 encode_utf8/;
  23         11910  
  23         1422  
49 23     23   161 use B;
  23         44  
  23         94011  
50              
51             our $VERSION = '0.34';
52              
53             sub create_json
54             {
55 60     60 0 104236 my ($input, %options) = @_;
56 60         187 my $jc = bless {
57             output => '',
58             };
59 60         217 $jc->{_strict} = !! $options{strict};
60 60         141 $jc->{_indent} = !! $options{indent};
61 60         122 $jc->{_sort} = !! $options{sort};
62 60 100       167 if ($jc->{_indent}) {
63 2         5 $jc->{depth} = 0;
64             }
65 60         156 my $error = create_json_recursively ($jc, $input);
66 60 100       132 if ($error) {
67 8         35 $jc->user_error ($error);
68 8         64 delete $jc->{output};
69 8         63 return undef;
70             }
71 52         333 return $jc->{output};
72             }
73              
74             sub create_json_strict
75             {
76 23     23 0 42025 my ($input, %options) = @_;
77 23         69 $options{strict} = 1;
78 23         79 return create_json ($input, %options);
79             }
80              
81             # http://stackoverflow.com/questions/1185822/how-do-i-create-or-test-for-nan-or-infinity-in-perl#1185828
82              
83             sub isinf {
84 205     205 0 444 $_[0]==9**9**9;
85             }
86              
87             sub isneginf {
88 202     202 0 457 $_[0]==-9**9**9;
89             }
90              
91             sub isnan {
92 208     208 0 583 return ! defined( $_[0] <=> 9**9**9 );
93             }
94              
95             sub isfloat
96             {
97 199     199 0 323 my ($num) = @_;
98              
99 199 100       433 if ($num != int ($num)) {
100             # It's clearly a floating point number
101 79         159 return 1;
102             }
103              
104             # To get the same result as the XS version we have to poke around
105             # with the following. I cannot actually see what to do in the XS
106             # so that I get the same printed numbers as Perl, it seems like
107             # Perl is really monkeying around with NVs so as to print them
108             # like integers when it can do so sensibly, and it doesn't make
109             # the "I'm gonna monkey with this NV" information available to the
110             # Perl programmer.
111              
112 120         300 my $r = B::svref_2object (\$num);
113 120   33     489 my $isfloat = $r->isa("B::NV") || $r->isa("B::PVNV");
114 120         302 return $isfloat;
115             }
116              
117             # Built in booleans. The nasty PL_sv_(yes|no) stuff comes from
118             # JSON::Parse. The JSON::Create::Bool is from our own nice module.
119              
120             sub isbool
121             {
122 371     371 0 596 my ($input, $ref) = @_;
123 371         1092 my $poo = B::svref_2object ($ref);
124 371 100       897 if (ref $poo eq 'B::SPECIAL') {
125             # Leave the following commented-out code as reference for what
126             # the magic numbers mean.
127              
128             # if ($B::specialsv_name[$$poo] eq '&PL_sv_yes') {
129 4 100       12 if ($$poo == 2) {
    50          
130 2         5 return 'true';
131             }
132             # elsif ($B::specialsv_name[$$poo] eq '&PL_sv_no') {
133             elsif ($$poo == 3) {
134 2         5 return 'false';
135             }
136             }
137 367         766 return undef;
138             }
139              
140             sub json_escape
141             {
142 328     328 0 531 my ($input) = @_;
143 328         837 $input =~ s/("|\\)/\\$1/g;
144 328         599 $input =~ s/\x08/\\b/g;
145 328         447 $input =~ s/\f/\\f/g;
146 328         453 $input =~ s/\n/\\n/g;
147 328         470 $input =~ s/\r/\\r/g;
148 328         431 $input =~ s/\t/\\t/g;
149 328         548 $input =~ s/([\x00-\x1f])/sprintf ("\\u%04x", ord ($1))/ge;
  4         26  
150 328         620 return $input;
151             }
152              
153             sub escape_all_unicode
154             {
155 6     6 0 9 my ($jc, $input) = @_;
156 6         8 my $format = "\\u%04x";
157 6 100       13 if ($jc->{_unicode_upper}) {
158 1         2 $format = "\\u%04X";
159             }
160 6         23 $input =~ s/([\x{007f}-\x{ffff}])/sprintf ($format, ord ($1))/ge;
  12         41  
161             # Convert U+10000 to U+10FFFF into surrogate pairs
162 6         23 $input =~ s/([\x{10000}-\x{10ffff}])/
163 9         47 sprintf ($format, 0xD800 | (((ord ($1)-0x10000) >>10) & 0x3ff)) .
164             sprintf ($format, 0xDC00 | ((ord ($1)) & 0x3ff))
165             /gex;
166 6         14 return $input;
167             }
168              
169             sub stringify
170             {
171 332     332 0 586 my ($jc, $input) = @_;
172 332 100       751 if (! utf8::is_utf8 ($input)) {
173 241 100 100     716 if ($input =~ /[\x{80}-\x{FF}]/ && $jc->{_strict}) {
174 3         7 return "Non-ASCII byte in non-utf8 string";
175             }
176 238 100       620 if (! valid_utf8 ($input)) {
177 2 100       4 if ($jc->{_replace_bad_utf8}) {
178             # Discard the warnings from Unicode::UTF8.
179 1     2   7 local $SIG{__WARN__} = sub {};
180 1         14 $input = decode_utf8 ($input);
181             }
182             else {
183 1         4 return 'Invalid UTF-8';
184             }
185             }
186             }
187 328         551 $input = json_escape ($input);
188 328 100       751 if ($jc->{_escape_slash}) {
189 2         9 $input =~ s!/!\\/!g;
190             }
191 328 100       649 if (! $jc->{_no_javascript_safe}) {
192 326         633 $input =~ s/\x{2028}/\\u2028/g;
193 326         547 $input =~ s/\x{2029}/\\u2029/g;
194             }
195 328 100       592 if ($jc->{_unicode_escape_all}) {
196 6         12 $input = $jc->escape_all_unicode ($input);
197             }
198 328         695 $jc->{output} .= "\"$input\"";
199 328         576 return undef;
200             }
201              
202             sub validate_user_json
203             {
204 2     2 0 6 my ($jc, $json) = @_;
205 2         4 eval {
206 2         25 JSON::Parse::assert_valid_json ($json);
207             };
208 2 100       7 if ($@) {
209 1         5 return "JSON::Parse::assert_valid_json failed for '$json': $@";
210             }
211 1         13 return undef;
212             }
213              
214             sub call_to_json
215             {
216 11     11 0 27 my ($jc, $cv, $r) = @_;
217 11 50       31 if (ref $cv ne 'CODE') {
218 0         0 confess "Not code";
219             }
220 11         16 my $json = &{$cv} ($r);
  11         28  
221 11 100       157 if (! defined $json) {
222 3         8 return 'undefined value from user routine';
223             }
224 8 100       24 if ($jc->{_validate}) {
225 2         7 my $error = $jc->validate_user_json ($json);
226 2 100       7 if ($error) {
227 1         3 return $error;
228             }
229             }
230 7         18 $jc->{output} .= $json;
231 7         13 return undef;
232             }
233              
234             # This handles a non-finite floating point number, which is either
235             # nan, inf, or -inf. The return value is undefined if successful, or
236             # the error value if an error occurred.
237              
238             sub handle_non_finite
239             {
240 9     9 0 17 my ($jc, $input, $type) = @_;
241 9         16 my $handler = $jc->{_non_finite_handler};
242 9 100       19 if ($handler) {
243 3         4 my $output = &{$handler} ($type);
  3         12  
244 3 50       12 if (! $output) {
245 0         0 return "Empty output from non-finite handler";
246             }
247 3         6 $jc->{output} .= $output;
248 3         9 return undef;
249             }
250 6 100       10 if ($jc->{_strict}) {
251 3         10 return "non-finite number";
252             }
253 3         19 $jc->{output} .= "\"$type\"";
254 3         12 return undef;
255             }
256              
257             sub handle_number
258             {
259 208     208 0 366 my ($jc, $input) = @_;
260             # Perl thinks that nan, inf, etc. look like numbers.
261 208 100       313 if (isnan ($input)) {
    100          
    100          
    50          
262 3         8 return $jc->handle_non_finite ($input, 'nan');
263             }
264             elsif (isinf ($input)) {
265 3         9 return $jc->handle_non_finite ($input, 'inf');
266             }
267             elsif (isneginf ($input)) {
268 3         8 return $jc->handle_non_finite ($input, '-inf');
269             }
270             elsif (isfloat ($input)) {
271             # Default format
272 199 100       370 if ($jc->{_fformat}) {
273             # Override. Validation is in
274             # JSON::Create::set_fformat.
275 57         246 $jc->{output} .= sprintf ($jc->{_fformat}, $input);
276             }
277             else {
278 142         743 $jc->{output} .= sprintf ("%.*g", 10, $input);
279             }
280             }
281             else {
282             # integer or looks like integer.
283 0         0 $jc->{output} .= $input;
284             }
285 199         439 return undef;
286             }
287              
288             sub newline_indent
289             {
290 117     117 0 174 my ($jc) = @_;
291 117         312 $jc->{output} .= "\n" . "\t" x $jc->{depth};
292             }
293              
294             sub openB
295             {
296 112     112 0 205 my ($jc, $b) = @_;
297 112         276 $jc->{output} .= $b;
298 112 100       286 if ($jc->{_indent}) {
299 23         31 $jc->{depth}++;
300 23         54 $jc->newline_indent ();
301             }
302             }
303              
304             sub closeB
305             {
306 102     102 0 202 my ($jc, $b) = @_;
307 102 100       255 if ($jc->{_indent}) {
308 23         31 $jc->{depth}--;
309 23         38 $jc->newline_indent ();
310             }
311 102         183 $jc->{output} .= $b;
312 102 100       239 if ($jc->{_indent}) {
313 23 100       56 if ($jc->{depth} == 0) {
314 6         11 $jc->{output} .= "\n";
315             }
316             }
317             }
318              
319             sub comma
320             {
321 262     262 0 404 my ($jc) = @_;
322 262         426 $jc->{output} .= ',';
323 262 100       519 if ($jc->{_indent}) {
324 71         119 $jc->newline_indent ();
325             }
326             }
327              
328             sub array
329             {
330 33     33 0 75 my ($jc, $input) = @_;
331 33         96 $jc->openB ('[');
332 33         52 my $i = 0;
333 33         73 for my $k (@$input) {
334 163 100       305 if ($i != 0) {
335 130         220 $jc->comma ();
336             }
337 163         209 $i++;
338 163         329 my $error = create_json_recursively ($jc, $k, \$k);
339 163 100       355 if ($error) {
340 1         3 return $error;
341             }
342             }
343 32         86 $jc->closeB (']');
344 32         56 return undef;
345             }
346              
347             sub object
348             {
349 79     79 0 149 my ($jc, $input) = @_;
350 79         242 $jc->openB ('{');
351 79         258 my @keys = keys %$input;
352 79 100       194 if ($jc->{_sort}) {
353 17 100       32 if ($jc->{cmp}) {
354 2         9 @keys = sort {&{$jc->{cmp}} ($a, $b)} @keys;
  10         43  
  10         17  
355             }
356             else {
357 15         53 @keys = sort @keys;
358             }
359             }
360 79         127 my $i = 0;
361 79         155 for my $k (@keys) {
362 210 100       463 if ($i != 0) {
363 132         266 $jc->comma ();
364             }
365 210         295 $i++;
366 210         275 my $error;
367 210         427 $error = stringify ($jc, $k);
368 210 100       416 if ($error) {
369 2         5 return $error;
370             }
371 208         327 $jc->{output} .= ':';
372 208         576 $error = create_json_recursively ($jc, $input->{$k}, \$input->{$k});
373 208 100       455 if ($error) {
374 7         20 return $error;
375             }
376             }
377 70         209 $jc->closeB ('}');
378 70         163 return undef;
379             }
380             sub newline_for_top
381             {
382 341     341 0 562 my ($jc) = @_;
383 341 100 100     921 if ($jc->{_indent} && $jc->{depth} == 0) {
384 1         3 $jc->{output} .= "\n";
385             }
386             }
387              
388             sub create_json_recursively
389             {
390 486     486 0 870 my ($jc, $input, $input_ref) = @_;
391 486 100       989 if ($input_ref) {
392 371         675 my $bool = isbool ($input, $input_ref);
393 371 100       713 if ($bool) {
394 4         8 $jc->{output} .= $bool;
395 4         9 $jc->newline_for_top ();
396 4         8 return undef;
397             }
398             }
399 482 100       917 if (! defined $input) {
400 8         21 $jc->{output} .= 'null';
401 8         29 $jc->newline_for_top ();
402 8         18 return undef;
403             }
404 474         770 my $ref = ref ($input);
405 474 100       906 if ($ref eq 'JSON::Create::Bool') {
406 4 100       20 if ($$input) {
407 2         8 $jc->{output} .= 'true';
408             }
409             else {
410 2         7 $jc->{output} .= 'false';
411             }
412 4         16 $jc->newline_for_top ();
413 4         10 return undef;
414             }
415 470 100 100     607 if (! keys %{$jc->{_handlers}} && ! $jc->{_obj_handler}) {
  470         2137  
416 440         664 my $origref = $ref;
417             # Break encapsulation if the user has not supplied handlers.
418 440         910 $ref = reftype ($input);
419 440 100 100     1016 if ($ref && $jc->{_strict}) {
420 29 100       73 if ($ref ne $origref) {
421 1         5 return "Object cannot be serialized to JSON: $origref";
422             }
423             }
424             }
425 469 100       880 if ($ref) {
426 139 100       363 if ($ref eq 'HASH') {
    100          
    100          
427 79         239 my $error = $jc->object ($input);
428 79 100       220 if ($error) {
429 9         16 return $error;
430             }
431             }
432             elsif ($ref eq 'ARRAY') {
433 33         105 my $error = $jc->array ($input);
434 33 100       65 if ($error) {
435 1         2 return $error;
436             }
437             }
438             elsif ($ref eq 'SCALAR') {
439 6 100       16 if ($jc->{_strict}) {
440 2         5 return "Input's type cannot be serialized to JSON";
441             }
442 4         25 my $error = $jc->create_json_recursively ($$input);
443 4 50       11 if ($error) {
444 0         0 return $error;
445             }
446             }
447             else {
448 21 100       77 if (blessed ($input)) {
449 18 100       40 if ($jc->{_obj_handler}) {
450 1         4 my $error = call_to_json ($jc, $jc->{_obj_handler}, $input);
451 1 50       4 if ($error) {
452 1         3 return $error;
453             }
454             }
455             else {
456 17         33 my $handler = $jc->{_handlers}{$ref};
457 17 50       31 if ($handler) {
458 17 100       46 if ($handler eq 'bool') {
    50          
459 9 100       54 if ($$input) {
460 6         16 $jc->{output} .= 'true';
461             }
462             else {
463 3         7 $jc->{output} .= 'false';
464             }
465             }
466             elsif (ref ($handler) eq 'CODE') {
467 8         20 my $error = $jc->call_to_json ($handler, $input);
468 8 100       21 if ($error) {
469 2         7 return $error;
470             }
471             }
472             else {
473 0         0 confess "Unknown handler type " . ref ($handler);
474             }
475             }
476             else {
477 0         0 return "$ref cannot be serialized.\n";
478             }
479             }
480             }
481             else {
482 3 100       7 if ($jc->{_type_handler}) {
483 2         9 my $error = call_to_json ($jc, $jc->{_type_handler}, $input);
484 2 100       5 if ($error) {
485 1         3 return $error;
486             }
487             }
488             else {
489 1         4 return "$ref cannot be serialized.\n";
490             }
491             }
492             }
493             }
494             else {
495 330         428 my $error;
496 330 100 100     1387 if (looks_like_number ($input) && $input !~ /^0[^.]/) {
497 208         469 $error = $jc->handle_number ($input);
498             }
499             else {
500 122         239 $error = stringify ($jc, $input);
501             }
502 330 100       648 if ($error) {
503 5         13 return $error;
504             }
505 325         653 $jc->newline_for_top ();
506             }
507 447         774 return undef;
508             }
509              
510             sub user_error
511             {
512 15     15 0 46 my ($jc, $error) = @_;
513 15 100       42 if ($jc->{_fatal_errors}) {
514 2         17 die $error;
515             }
516             else {
517 13         180 warn $error;
518             }
519             }
520              
521             sub new
522             {
523 24     24 0 95 return bless {
524             _handlers => {},
525             };
526             }
527              
528             sub strict
529             {
530 2     2 0 12 my ($jc, $onoff) = @_;
531 2         11 $jc->{_strict} = !! $onoff;
532             }
533              
534             sub get_handlers
535             {
536 8     8 0 18 my ($jc) = @_;
537 8         20 return $jc->{_handlers};
538             }
539              
540             sub non_finite_handler
541             {
542 1     1 0 14 my ($jc, $handler) = @_;
543 1         3 $jc->{_non_finite_handler} = $handler;
544 1         3 return undef;
545             }
546              
547             sub bool
548             {
549 4     4 0 813 my ($jc, @list) = @_;
550 4         13 my $handlers = $jc->get_handlers ();
551 4         12 for my $k (@list) {
552 4         15 $handlers->{$k} = 'bool';
553             }
554             }
555              
556             sub cmp
557             {
558 1     1 0 9 my ($jc, $cmp) = @_;
559 1         3 $jc->{cmp} = $cmp;
560             }
561              
562             sub escape_slash
563             {
564 2     2 0 3451 my ($jc, $onoff) = @_;
565 2         7 $jc->{_escape_slash} = !! $onoff;
566             }
567              
568             sub fatal_errors
569             {
570 4     4 0 762 my ($jc, $onoff) = @_;
571 4         14 $jc->{_fatal_errors} = !! $onoff;
572             }
573              
574             sub indent
575             {
576 5     5 0 21 my ($jc, $onoff) = @_;
577 5         40 $jc->{_indent} = !! $onoff;
578             }
579              
580             sub no_javascript_safe
581             {
582 2     2 0 946 my ($jc, $onoff) = @_;
583 2         6 $jc->{_no_javascript_safe} = !! $onoff;
584             }
585              
586             sub obj
587             {
588 4     4 0 833 my ($jc, %things) = @_;
589 4         16 my $handlers = $jc->get_handlers ();
590 4         13 for my $k (keys %things) {
591 5         15 $handlers->{$k} = $things{$k};
592             }
593             }
594              
595             sub obj_handler
596             {
597 1     1 0 9 my ($jc, $handler) = @_;
598 1         30 $jc->{_obj_handler} = $handler;
599             }
600              
601             sub replace_bad_utf8
602             {
603 1     1 0 236 my ($jc, $onoff) = @_;
604 1         3 $jc->{_replace_bad_utf8} = !! $onoff;
605             }
606              
607             sub run
608             {
609 0     0 0 0 goto &create;
610             }
611              
612             sub create
613             {
614 51     51 0 22567 my ($jc, $input) = @_;
615 51         130 $jc->{output} = '';
616 51         140 my $error = create_json_recursively ($jc, $input);
617 51 100       165 if ($error) {
618 7         24 $jc->user_error ($error);
619 5         41 delete $jc->{output};
620 5         13 return undef;
621             }
622 44 100       91 if ($jc->{_downgrade_utf8}) {
623 1         5 $jc->{output} = encode_utf8 ($jc->{output});
624             }
625 44         134 return $jc->{output};
626             }
627              
628             sub set_fformat
629             {
630 4     4 0 959 my ($jc, $fformat) = @_;
631 4         12 JSON::Create::set_fformat ($jc, $fformat);
632             }
633              
634             sub set_fformat_unsafe
635             {
636 4     4 0 10 my ($jc, $fformat) = @_;
637 4 100       9 if ($fformat) {
638 2         12 $jc->{_fformat} = $fformat;
639             }
640             else {
641 2         7 delete $jc->{_fformat};
642             }
643             }
644              
645             sub set_validate
646             {
647 1     1 0 3 my ($jc, $onoff) = @_;
648 1         53 $jc->{_validate} = !! $onoff;
649             }
650              
651             sub JSON::Create::PP::sort
652             {
653 4     4 0 17 my ($jc, $onoff) = @_;
654 4         20 $jc->{_sort} = !! $onoff;
655             }
656              
657             sub downgrade_utf8
658             {
659 2     2 0 349 my ($jc, $onoff) = @_;
660 2         11 $jc->{_downgrade_utf8} = !! $onoff;
661             }
662              
663             sub set
664             {
665 25     25 0 75 my ($jc, %args) = @_;
666 25         100 for my $k (keys %args) {
667 4         9 my $value = $args{$k};
668              
669             # Options are in alphabetical order
670              
671 4 50       12 if ($k eq 'bool') {
672 0         0 $jc->bool (@$value);
673 0         0 next;
674             }
675 4 50       10 if ($k eq 'cmp') {
676 0         0 $jc->cmp ($value);
677 0         0 next;
678             }
679 4 50       7 if ($k eq 'downgrade_utf8') {
680 0         0 $jc->downgrade_utf8 ($value);
681 0         0 next;
682             }
683 4 50       9 if ($k eq 'escape_slash') {
684 0         0 $jc->escape_slash ($value);
685 0         0 next;
686             }
687 4 50       6 if ($k eq 'fatal_errors') {
688 0         0 $jc->fatal_errors ($value);
689 0         0 next;
690             }
691 4 100       10 if ($k eq 'indent') {
692 2         9 $jc->indent ($value);
693 2         4 next;
694             }
695 2 50       5 if ($k eq 'no_javascript_safe') {
696 0         0 $jc->no_javascript_safe ($value);
697 0         0 next;
698             }
699 2 50       4 if ($k eq 'non_finite_handler') {
700 0         0 $jc->non_finite_handler ($value);
701 0         0 next;
702             }
703 2 50       6 if ($k eq 'obj_handler') {
704 0         0 $jc->obj_handler ($value);
705 0         0 next;
706             }
707 2 50       6 if ($k eq 'replace_bad_utf8') {
708 0         0 $jc->replace_bad_utf8 ($value);
709 0         0 next;
710             }
711 2 50       5 if ($k eq 'sort') {
712 2         7 $jc->sort ($value);
713 2         5 next;
714             }
715 0 0       0 if ($k eq 'strict') {
716 0         0 $jc->strict ($value);
717 0         0 next;
718             }
719 0 0       0 if ($k eq 'unicode_upper') {
720 0         0 $jc->unicode_upper ($value);
721 0         0 next;
722             }
723 0 0       0 if ($k eq 'validate') {
724 0         0 $jc->validate ($value);
725 0         0 next;
726             }
727 0         0 warn "Unknown option '$k'";
728             }
729             }
730              
731             sub type_handler
732             {
733 2     2 0 13 my ($jc, $handler) = @_;
734 2         11 $jc->{_type_handler} = $handler;
735             }
736              
737             sub unicode_escape_all
738             {
739 3     3 0 466 my ($jc, $onoff) = @_;
740 3         7 $jc->{_unicode_escape_all} = !! $onoff;
741             }
742              
743             sub unicode_upper
744             {
745 3     3 0 553 my ($jc, $onoff) = @_;
746 3         7 $jc->{_unicode_upper} = !! $onoff;
747             }
748              
749             sub validate
750             {
751 1     1 0 1150 return JSON::Create::validate (@_);
752             }
753              
754             sub write_json
755             {
756             # Parent module function is pure perl.
757 0     0 0   JSON::Create::write_json (@_);
758             }
759              
760             1;