1 package JSON::object_unknown;
6 my $x = shift || $class;
7 return bless \$x => __PACKAGE__;
9 use overload ( '""' => \&toString );
10 use overload ( '0+' => sub { $_[0]->toString } );
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 ( '%' => sub { int($_[0]) % int($_[1]) } );
16 use overload ( '**' => sub { int($_[0]) ** int($_[1]) } );
17 use overload ( 'neg' => sub { neg(int($_[0])) } );
19 sub toString { defined($_[1]) ? ${$_[1]} : ${$_[0]} }
21 package JSON::bool::true;
22 sub new { return bless {} => __PACKAGE__ }
23 use overload ( '""' => \&toString );
24 use overload ( 'bool' => sub { 1 } );
25 use overload ( '0+' => sub { 1 } );
27 sub toString { 'true' }
29 package JSON::bool::false;
30 sub new { return bless {} => __PACKAGE__ }
31 use overload ( '""' => \&toString );
32 use overload ( 'bool' => sub { 0 } );
33 use overload ( '0+' => sub { 0 } );
35 sub toString { 'false' }
38 use vars qw/%_class_map/;
40 sub register_class_hint {
44 $args{hint_re} = qr/(?:\b$args{hint})\b/;
45 $args{class_re} = qr/(?:\b$args{name})\b/;
47 $_class_map{hints}{$args{hint}} = \%args;
48 $_class_map{classes}{$args{name}} = \%args;
50 JSON->register_class_hint(
51 name => 'JSON::object_unknown',
61 -?\d+\.?\d* | # number literal
62 "(?:(?:\\[\"])|[^\"])*" | # string literal
63 (?:\/\*.+?\*\/) | # C comment
67 : | # object key-value sep
76 sub _json_hint_to_class {
78 return $_class_map{hints}{$hint}{name} if (exists $_class_map{hints}{$hint});
79 return 'JSON::object_unknown';
87 my @strings = /"((?:(?:\\[\"])|[^\"])*)"/sog;
88 # Replace with code...
89 s/"(?:(?:\\[\"])|[^\"])*"/ shift(\@strings) /sog;
92 # handle class blessings
93 s/\/\*--\s*S\w*?\s+\S+\s*--\*\// bless(/sog;
94 s/\/\*--\s*E\w*?\s+(\S+)\s*--\*\// => _json_hint_to_class("$1")) /sog;
98 for my $hint (values %{$_class_map{hints}}) {
99 $string =~ s/\/\*--\s*S\w*?\s+$$hint{hint_re}\s*--\*\// bless(/sog;
100 $string =~ s/\/\*--\s*E\w*?\s+$$hint{hint_re}\s*--\*\// => "$$hint{name}") /sog;
101 warn $$hint{name}."\n\n";
102 warn ' '.$string."\n\n";
105 s/\/\*--\s*\w+\s+\S+\s*--\*\///sog;
109 s/\b(-?\d+\.?\d*)/ do { JSON::number::new($1) } /sog;
111 # Change javascript stuff to perl...
114 s/true/ bless( {}, "JSON::bool::true") /sog;
115 s/false/ bless( {}, "JSON::bool::false") /sog;
118 return eval '$ret = '.$_;
122 my ($class, $json) = @_;
124 if (!defined($json)) {
128 #$json =~ s/\/\/.+$//gmo; # remove C++ comments
129 $json =~ s/(?<!\\)\$/\\\$/gmo; # fixup $ for later
130 $json =~ s/(?<!\\)\@/\\\@/gmo; # fixup @ for later
133 my $casting_depth = 0;
137 while (($json,$element) = _JSON_regex($json)) {
139 last unless ($element);
141 if ($element eq 'null') {
142 $output .= ' undef() ';
144 } elsif ($element =~ /^\/\*--\s*S\w*?\s+(\w+)\s*--\*\/$/) {
146 if (exists $_class_map{hints}{$hint}) {
147 $casts[$casting_depth] = $hint;
148 $output .= ' bless(';
151 } elsif ($element =~ /^\/\*/) {
153 } elsif ($element =~ /^\d/) {
154 $output .= "do { JSON::number::new($element) }";
156 } elsif ($element eq '{' or $element eq '[') {
158 } elsif ($element eq '}' or $element eq ']') {
160 my $hint = $casts[$casting_depth];
161 $casts[$casting_depth] = undef;
162 if (defined $hint and exists $_class_map{hints}{$hint}) {
163 $output .= $element . ',"'. $_class_map{hints}{$hint}{name} . '")';
166 } elsif ($element eq ':') {
169 } elsif ($element eq 'true') {
170 $output .= 'bless( {}, "JSON::bool::true")';
172 } elsif ($element eq 'false') {
173 $output .= 'bless( {}, "JSON::bool::false")';
184 my ($class, $perl) = @_;
187 if (!defined($perl)) {
189 } elsif (ref($perl) and ref($perl) =~ /^JSON/) {
191 } elsif ( ref($perl) && exists($_class_map{classes}{ref($perl)}) ) {
192 $output .= '/*--S '.$_class_map{classes}{ref($perl)}{hint}.'--*/';
193 if (lc($_class_map{classes}{ref($perl)}{type}) eq 'hash') {
195 $output .= perl2JSON(undef,\%hash);
196 } elsif (lc($_class_map{classes}{ref($perl)}{type}) eq 'array') {
198 $output .= perl2JSON(undef,\@array);
200 $output .= '/*--E '.$_class_map{classes}{ref($perl)}{hint}.'--*/';
201 } elsif (ref($perl) and ref($perl) =~ /HASH/) {
204 for my $key (sort keys %$perl) {
205 $output .= ',' if ($c);
207 $output .= perl2JSON(undef,$key).':'.perl2JSON(undef,$$perl{$key});
211 } elsif (ref($perl) and ref($perl) =~ /ARRAY/) {
214 for my $part (@$perl) {
215 $output .= ',' if ($c);
217 $output .= perl2JSON(undef,$part);
222 $perl =~ s/\\/\\\\/sgo;
223 $perl =~ s/"/\\"/sgo;
224 $perl =~ s/\t/\\t/sgo;
225 $perl =~ s/\f/\\f/sgo;
226 $perl =~ s/\r/\\r/sgo;
227 $perl =~ s/\n/\\n/sgo;
228 $output = '"'.$perl.'"';
235 sub perl2prettyJSON {
236 my ($class, $perl, $nospace) = @_;
240 if (!defined($perl)) {
242 } elsif (ref($perl) and ref($perl) =~ /^JSON/) {
244 } elsif ( ref($perl) && exists($_class_map{classes}{ref($perl)}) ) {
247 $output .= " "x$depth;
248 $output .= '/*--S '.$_class_map{classes}{ref($perl)}{hint}."--*/ ";
249 if (lc($_class_map{classes}{ref($perl)}{type}) eq 'hash') {
251 $output .= perl2prettyJSON(\%hash,undef,1);
252 } elsif (lc($_class_map{classes}{ref($perl)}{type}) eq 'array') {
254 $output .= perl2prettyJSON(\@array,undef,1);
256 #$output .= " "x$depth;
257 $output .= ' /*--E '.$_class_map{classes}{ref($perl)}{hint}.'--*/';
259 } elsif (ref($perl) and ref($perl) =~ /HASH/) {
261 $output .= " "x$depth unless ($nospace);
265 for my $key (sort keys %$perl) {
266 $output .= ",\n" if ($c);
268 $output .= perl2prettyJSON($key)." : ".perl2prettyJSON($$perl{$key}, undef, 1);
273 $output .= " "x$depth;
276 } elsif (ref($perl) and ref($perl) =~ /ARRAY/) {
278 $output .= " "x$depth unless ($nospace);
282 for my $part (@$perl) {
283 $output .= ",\n" if ($c);
285 $output .= perl2prettyJSON($part);
290 $output .= " "x$depth;
294 $perl =~ s/\\/\\\\/sgo;
295 $perl =~ s/"/\\"/sgo;
296 $perl =~ s/\t/\\t/sgo;
297 $perl =~ s/\f/\\f/sgo;
298 $perl =~ s/\r/\\r/sgo;
299 $perl =~ s/\n/\\n/sgo;
300 $output .= " "x$depth unless($nospace);
301 $output .= '"'.$perl.'"';