4 my $x = shift || $class;
5 return bless \$x => __PACKAGE__;
7 use overload ( '""' => \&toString );
8 use overload ( '0+' => sub { $_[0]->toString } );
9 use overload ( '+' => sub { int($_[0]) + int($_[1]) } );
10 use overload ( '-' => sub { int($_[0]) - int($_[1]) } );
11 use overload ( '*' => sub { int($_[0]) * int($_[1]) } );
12 use overload ( '/' => sub { int($_[0]) / int($_[1]) } );
13 use overload ( '%' => sub { int($_[0]) % int($_[1]) } );
14 use overload ( '**' => sub { int($_[0]) ** int($_[1]) } );
15 use overload ( 'neg' => sub { neg(int($_[0])) } );
17 sub toString { defined($_[1]) ? ${$_[1]} : ${$_[0]} }
19 package JSON::bool::true;
20 sub new { return bless {} => __PACKAGE__ }
21 use overload ( '""' => \&toString );
22 use overload ( 'bool' => sub { 1 } );
23 use overload ( '0+' => sub { 1 } );
25 sub toString { 'true' }
27 package JSON::bool::false;
28 sub new { return bless {} => __PACKAGE__ }
29 use overload ( '""' => \&toString );
30 use overload ( 'bool' => sub { 0 } );
31 use overload ( '0+' => sub { 0 } );
33 sub toString { 'false' }
36 use vars qw/%_class_map/;
38 sub register_class_hint {
42 $_class_map{$args{hint}} = \%args;
43 $_class_map{$args{name}} = \%args;
52 -?\d+\.?\d* | # number literal
53 "(?:(?:\\[\"])|[^\"])*" | # string literal
54 (?:\/\*.+?\*\/) | # C comment
58 : | # object key-value sep
72 my @strings = /(?:"((?:(?:\\[\"])|[^\"])*)")/sog;
73 # Replace with code...
74 s/(?:"(?:(?:\\[\"])|[^\"])*")/ shift(\@strings) /sog;
76 # handle class blessings
77 s/\/\*--\s*S\w*?\s+\w+\s*--\*\// bless(/sog;
78 s/\/\*--\s*E\w*?\s+(\w+)\s*--\*\// , "$_class_map{$1}{name}") /sog;
80 # Change javascript stuff to perl...
82 #s/(true|false)/ bless( {}, "JSON::bool::$1") /sog;
83 s/true/ bless( {}, "JSON::bool::true") /sog;
84 s/false/ bless( {}, "JSON::bool::false") /sog;
85 s/\b(-?\d+\.?\d*)/ do { JSON::number::new($1) } /sog;
91 my ($class, $json) = @_;
93 if (!defined($json)) {
97 #$json =~ s/\/\/.+$//gmo; # remove C++ comments
98 $json =~ s/(?<!\\)\$/\\\$/gmo; # fixup $ for later
99 $json =~ s/(?<!\\)\@/\\\@/gmo; # fixup @ for later
102 my $casting_depth = 0;
106 while (($json,$element) = _JSON_regex($json)) {
108 last unless ($element);
110 if ($element eq 'null') {
111 $output .= ' undef() ';
113 } elsif ($element =~ /^\/\*--\s*S\w*?\s+(\w+)\s*--\*\/$/) {
115 if (exists $_class_map{$hint}) {
116 $casts[$casting_depth] = $hint;
117 $output .= ' bless(';
120 } elsif ($element =~ /^\/\*/) {
122 } elsif ($element =~ /^\d/) {
123 $output .= "do { JSON::number::new($element) }";
125 } elsif ($element eq '{' or $element eq '[') {
127 } elsif ($element eq '}' or $element eq ']') {
129 my $hint = $casts[$casting_depth];
130 $casts[$casting_depth] = undef;
131 if (defined $hint and exists $_class_map{$hint}) {
132 $output .= $element . ',"'. $_class_map{$hint}{name} . '")';
135 } elsif ($element eq ':') {
138 } elsif ($element eq 'true') {
139 $output .= 'bless( {}, "JSON::bool::true")';
141 } elsif ($element eq 'false') {
142 $output .= 'bless( {}, "JSON::bool::false")';
153 my ($class, $perl) = @_;
156 if (!defined($perl)) {
158 } elsif (ref($perl) and ref($perl) =~ /^JSON/) {
160 } elsif ( ref($perl) && exists($_class_map{ref($perl)}) ) {
161 $output .= '/*--S '.$_class_map{ref($perl)}{hint}.'--*/';
162 if (lc($_class_map{ref($perl)}{type}) eq 'hash') {
164 $output .= perl2JSON(undef,\%hash);
165 } elsif (lc($_class_map{ref($perl)}{type}) eq 'array') {
167 $output .= perl2JSON(undef,\@array);
169 $output .= '/*--E '.$_class_map{ref($perl)}{hint}.'--*/';
170 } elsif (ref($perl) and ref($perl) =~ /HASH/) {
173 for my $key (sort keys %$perl) {
174 $output .= ',' if ($c);
176 $output .= perl2JSON(undef,$key).':'.perl2JSON(undef,$$perl{$key});
180 } elsif (ref($perl) and ref($perl) =~ /ARRAY/) {
183 for my $part (@$perl) {
184 $output .= ',' if ($c);
186 $output .= perl2JSON(undef,$part);
191 $perl =~ s/\\/\\\\/sgo;
192 $perl =~ s/"/\\"/sgo;
193 $perl =~ s/\t/\\t/sgo;
194 $perl =~ s/\f/\\f/sgo;
195 $perl =~ s/\r/\\r/sgo;
196 $perl =~ s/\n/\\n/sgo;
197 $output = '"'.$perl.'"';
204 sub perl2prettyJSON {
205 my ($class, $perl, $nospace) = @_;
209 if (!defined($perl)) {
211 } elsif (ref($perl) and ref($perl) =~ /^JSON/) {
213 } elsif ( ref($perl) && exists($_class_map{ref($perl)}) ) {
216 $output .= " "x$depth;
217 $output .= '/*--S '.$_class_map{ref($perl)}{hint}."--*/ ";
218 if (lc($_class_map{ref($perl)}{type}) eq 'hash') {
220 $output .= perl2prettyJSON(\%hash,undef,1);
221 } elsif (lc($_class_map{ref($perl)}{type}) eq 'array') {
223 $output .= perl2prettyJSON(\@array,undef,1);
225 #$output .= " "x$depth;
226 $output .= ' /*--E '.$_class_map{ref($perl)}{hint}.'--*/';
228 } elsif (ref($perl) and ref($perl) =~ /HASH/) {
230 $output .= " "x$depth unless ($nospace);
234 for my $key (sort keys %$perl) {
235 $output .= ",\n" if ($c);
237 $output .= perl2prettyJSON($key)." : ".perl2prettyJSON($$perl{$key}, undef, 1);
242 $output .= " "x$depth;
245 } elsif (ref($perl) and ref($perl) =~ /ARRAY/) {
247 $output .= " "x$depth unless ($nospace);
251 for my $part (@$perl) {
252 $output .= ",\n" if ($c);
254 $output .= perl2prettyJSON($part);
259 $output .= " "x$depth;
263 $perl =~ s/\\/\\\\/sgo;
264 $perl =~ s/"/\\"/sgo;
265 $perl =~ s/\t/\\t/sgo;
266 $perl =~ s/\f/\\f/sgo;
267 $perl =~ s/\r/\\r/sgo;
268 $perl =~ s/\n/\\n/sgo;
269 $output .= " "x$depth unless($nospace);
270 $output .= '"'.$perl.'"';