File Coverage

blib/lib/JSON/Util.pm
Criterion Covered Total %
statement 52 52 100.0
branch 7 10 70.0
condition n/a
subroutine 13 13 100.0
pod 5 5 100.0
total 77 80 96.2


line stmt bran cond sub pod time code
1             package JSON::Util;
2              
3             =head1 NAME
4              
5             JSON::Util - easy and portable encode/decode of JSON
6              
7             =head1 SYNOPSIS
8              
9             use JSON::Util;
10             $data = JSON::Util->decode('{"bar": "foo"}');
11             $data = JSON::Util->decode('some.json');
12             JSON::Util->encode({ 'foo' => 'bar' }, 'someother.json');
13              
14             $data = JSON::Util->decode(['..', 'folder', some.json]);
15             JSON::Util->encode([123,321], ['..', 'folder', someother.json]);
16              
17             print JSON::Util->encode([987,789]), "\n";
18             print JSON::Util->encode({987 => 789}), "\n";
19              
20             my $json = JSON::Util->new(pretty => 0, convert_blessed => 1);
21             print $json->encode([ $object, $object2 ]);
22              
23             # with file locking
24             $data = JSON::Util->decode(['..', 'folder', some.json], { 'LOCK_SH' => 1 });
25             $data = JSON::Util->decode(['..', 'folder', some.json], { 'LOCK_SH' => 1, LOCK_NB => 1 });
26             JSON::Util->encode([123,321], ['..', 'folder', someother.json], { 'LOCK_EX' => 1 });
27             JSON::Util->encode([123,321], ['..', 'folder', someother.json], { 'LOCK_EX' => 1, LOCK_NB => 1 });
28              
29             =head1 DESCRIPTION
30              
31             =cut
32              
33 1     1   134854 use warnings;
  1         1  
  1         25  
34 1     1   5 use strict;
  1         2  
  1         31  
35              
36             our $VERSION = '0.06';
37              
38 1     1   14 use 5.010;
  1         76  
39 1     1   4 use feature 'state';
  1         1  
  1         116  
40              
41 1     1   4 use Scalar::Util 'blessed';
  1         2  
  1         43  
42 1     1   5 use IO::Any;
  1         1  
  1         24  
43 1     1   3 use Carp 'croak';
  1         2  
  1         34  
44 1     1   5 use JSON::MaybeXS;
  1         1  
  1         541  
45              
46             =head1 METHODS
47              
48             =head2 new()
49              
50             Object constructor. Needed only when the L configuration
51             needs to be changed. Any key/value passed as parameter will be called on
52             C<new()>> as C<<$json->$key($value)>>.
53              
54             =cut
55              
56             sub new {
57 2     2 1 3 my $class = shift;
58 2         8 my %options = (
59             'utf8' => 1,
60             'pretty' => 1,
61             'convert_blessed' => 1,
62             @_
63             );
64              
65 2         5 my $self = bless \%options, __PACKAGE__;
66            
67 2         9 my $json = JSON::MaybeXS->new();
68 2         27 while (my ($option, $value) = each %options) {
69 6         26 $json->$option($value);
70             }
71              
72 2         6 $self->{'json'} = $json;
73            
74 2         6 return $self;
75             }
76              
77             =head2 default_json
78              
79             Returns C<new()>> with:
80              
81             'utf8' => 1,
82             'pretty' => 1,
83             'convert_blessed' => 1,
84              
85             =cut
86              
87             sub default_json {
88 5     5 1 7 my $class = shift;
89 5         9 state $json = $class->new->{'json'};
90 5         57 return $json;
91             }
92              
93             =head2 json
94              
95             Returns current L object.
96              
97             =cut
98              
99             sub json {
100 7 100   7 1 49 return (blessed $_[0] ? $_[0]->{'json'} : $_[0]->default_json);
101             }
102              
103             =head2 decode($what, [$opt])
104              
105             Return ref with decoded C<$what>. See L for C<$where> and C<$opt>
106             description.
107              
108             =cut
109              
110             sub decode {
111 3     3 1 3073 my $self = shift;
112 3         6 my $what = shift;
113 3         4 my $opt = shift;
114 3 50       8 croak 'too many arguments'
115             if @_;
116            
117 3         5 my $data = eval { $self->json->decode(IO::Any->slurp($what, $opt)) };
  3         9  
118 3         574 my $error = $@; $error =~ s/\n$//;
  3         5  
119 3 50       9 croak $error if $@;
120            
121 3         19 return $data;
122             }
123              
124             =head2 encode($data, [$where], [$opt])
125              
126             Returns encoded C<$data>. If C<$where> is passed then the result is
127             written there. See L for C<$where> and C<$opt> description.
128              
129             =cut
130              
131             sub encode {
132 4     4 1 193 my $self = shift;
133 4         6 my $data = shift;
134            
135             # with one argument just do json encode
136 4 100       12 return $self->json->encode($data)
137             if (@_ == 0);
138            
139 2         4 my $where = shift;
140 2         3 my $opt = shift;
141 2 50       5 croak 'too many arguments'
142             if @_;
143            
144 2         5 return IO::Any->spew($where, $self->json->encode($data), $opt);
145             }
146              
147             1;
148              
149              
150             __END__