root/branches/boomer/extlib/JSON/Converter.pm @ 1098

Revision 1098, 5.1 kB (checked in by hachi, 2 years ago)

Branching for boomer from release-19, rev 62318

Line 
1package JSON::Converter;
2##############################################################################
3
4use Carp;
5
6$JSON::Converter::VERSION = 0.995;
7
8##############################################################################
9
10sub new {
11    my $class = shift;
12    bless {indent => 2, pretty => 0, delimiter => 2, @_}, $class;
13}
14
15
16sub objToJson {
17        my $self = shift;
18        my $obj  = shift;
19        my $opt  = shift;
20
21        local(@{$self}{qw/autoconv execcoderef skipinvalid/});
22        local(@{$self}{qw/pretty indent delimiter/});
23
24        $self->_initConvert($opt);
25
26        return $self->toJson($obj);
27}
28
29
30sub toJson {
31        my ($self, $obj) = @_;
32
33        if(ref($obj) eq 'HASH'){
34                return $self->hashToJson($obj);
35        }
36        elsif(ref($obj) eq 'ARRAY'){
37                return $self->arrayToJson($obj);
38        }
39        else{
40                return;
41        }
42}
43
44
45sub hashToJson {
46        my $self = shift;
47        my $obj  = shift;
48        my ($k,$v);
49        my %res;
50
51        my ($pre,$post) = $self->_upIndent() if($self->{pretty});
52
53        if(grep { $_ == $obj } @{ $self->{_stack_myself} }){
54                die "circle ref!";
55        }
56
57        push @{ $self->{_stack_myself} },$obj;
58
59        for my $k (keys %$obj){
60                my $v = $obj->{$k};
61                if(ref($v) eq "HASH"){
62                        $res{$k} = $self->hashToJson($v);
63                }
64                elsif(ref($v) eq "ARRAY"){
65                        $res{$k} = $self->arrayToJson($v);
66                }
67                else{
68                        $res{$k} = $self->valueToJson($v);
69                }
70        }
71
72        pop @{ $self->{_stack_myself} };
73
74        $self->_downIndent() if($self->{pretty});
75
76        if($self->{pretty}){
77                my $del = $self->{_delstr};
78                return "{$pre"
79                 . join(",$pre", map { _stringfy($_) . $del .$res{$_} } keys %res)
80                 . "$post}";
81        }
82        else{
83                return '{'. join(',',map { _stringfy($_) .':' .$res{$_} } keys %res) .'}';
84        }
85
86}
87
88
89sub arrayToJson {
90        my $self = shift;
91        my $obj  = shift;
92        my @res;
93
94        my ($pre,$post) = $self->_upIndent() if($self->{pretty});
95
96        if(grep { $_ == $obj } @{ $self->{_stack_myself} }){
97                die "circle ref!";
98        }
99
100        push @{ $self->{_stack_myself} },$obj;
101
102        for my $v (@$obj){
103                if(ref($v) eq "HASH"){
104                        push @res,$self->hashToJson($v);
105                }
106                elsif(ref($v) eq "ARRAY"){
107                        push @res,$self->arrayToJson($v);
108                }
109                else{
110                        push @res,$self->valueToJson($v);
111                }
112        }
113
114        pop @{ $self->{_stack_myself} };
115
116        $self->_downIndent() if($self->{pretty});
117
118        if($self->{pretty}){
119                return "[$pre" . join(",$pre" ,@res) . "$post]";
120        }
121        else{
122                return '[' . join(',' ,@res) . ']';
123        }
124}
125
126
127sub valueToJson {
128        my $self  = shift;
129        my $value = shift;
130
131        return 'null' if(!defined $value);
132
133        if($self->{autoconv} and !ref($value)){
134                return $value  if($value =~ /^-?(?:0|[1-9][\d]*)(?:\.[\d]+)?$/);
135                return 'true'  if($value =~ /^true$/i);
136                return 'false' if($value =~ /^false$/i);
137        }
138
139        if(! ref($value) ){
140                return _stringfy($value)
141        }
142        elsif($self->{execcoderef} and ref($value) eq 'CODE'){
143                my $ret = $value->();
144                return 'null' if(!defined $ret);
145                return $self->toJson($ret) if(ref($ret));
146                return _stringfy($ret);
147        }
148        elsif( ! UNIVERSAL::isa($value, 'JSON::NotString') ){
149                die "Invalid value" unless($self->{skipinvalid});
150                return 'null';
151        }
152
153        return defined $value->{value} ? $value->{value} : 'null';
154}
155
156
157sub _stringfy {
158        my $arg = shift;
159        my $l   = length $arg;
160        my $s   = '"';
161        my $i = 0;
162
163        while($i < $l){
164                my $c = substr($arg,$i++,1);
165                if($c ge ' '){
166                        $c =~ s{(["\\])}{\\$1};
167                        $s .= $c;
168                }
169                elsif($c =~ tr/\n\r\t\f\b/nrtfb/){
170                        $s .= '\\' . $c;
171                }
172                else{
173                        $s .= '\\u00' . unpack('H2',$c);
174                }
175        }
176
177        return $s . '"';
178}
179
180
181##############################################################################
182
183sub _initConvert {
184        my $self = shift;
185        my %opt  = %{ $_[0] } if(@_ > 0 and ref($_[0]) eq 'HASH');
186
187        $self->{autoconv}    = $JSON::AUTOCONVERT if(!defined $self->{autoconv});
188        $self->{execcoderef} = $JSON::ExecCoderef if(!defined $self->{execcoderef});
189        $self->{skipinvalid} = $JSON::SkipInvalid if(!defined $self->{skipinvalid});
190
191        $self->{pretty}      =  $JSON::Pretty    if(!defined $self->{pretty});
192        $self->{indent}      =  $JSON::Indent    if(!defined $self->{indent});
193        $self->{delimiter}   =  $JSON::Delimiter if(!defined $self->{delimiter});
194
195        for my $name (qw/autoconv execcoderef skipinvalid pretty indent delimiter/){
196                $self->{$name} = $opt{$name} if(defined $opt{$name});
197        }
198
199        $self->{_stack_myself} = [];
200        $self->{indent_count}  = 0;
201
202        $self->{_delstr} = 
203                $self->{delimiter} ? ($self->{delimiter} == 1 ? ': ' : ' : ') : ':';
204
205        $self;
206}
207
208
209sub _upIndent {
210        my $self  = shift;
211        my $space = ' ' x $self->{indent};
212        my ($pre,$post) = ('','');
213
214        $post = "\n" . $space x $self->{indent_count};
215
216        $self->{indent_count}++;
217
218        $pre = "\n" . $space x $self->{indent_count};
219
220        return ($pre,$post);
221}
222
223
224sub _downIndent { $_[0]->{indent_count}--; }
225
226##############################################################################
2271;
228__END__
229
230
231=head1 METHODs
232
233=over
234
235=item parse
236
237alias of C<objToJson>.
238
239=item objToJson
240
241convert a passed perl data structure into JSON object.
242can't parse bleesed object.
243
244=item hashToJson
245
246convert a passed hash into JSON object.
247
248=item arrayToJson
249
250convert a passed array into JSON array.
251
252=item valueToJson
253
254convert a passed data into a string of JSON.
255
256=back
257
258=head1 COPYRIGHT
259
260makamaka [at] donzoko.net
261
262This library is free software; you can redistribute it
263and/or modify it under the same terms as Perl itself.
264
265=head1 SEE ALSO
266
267L<http://www.crockford.com/JSON/index.html>
268
269=cut
Note: See TracBrowser for help on using the browser.