4 my $x = shift || $class;
5 return bless \$x => __PACKAGE__;
7 use overload ( '""' => \&toString );
8 use overload ( '0+' => sub { ${$_[0]} } );
10 sub toString { defined($_[1]) ? ${$_[1]} : ${$_[0]} }
12 package JSON::bool::true;
13 sub new { return bless {} => __PACKAGE__ }
14 use overload ( '""' => \&toString );
15 use overload ( 'bool' => sub { 1 } );
16 use overload ( '0+' => sub { 1 } );
18 sub toString { 'true' }
20 package JSON::bool::false;
21 sub new { return bless {} => __PACKAGE__ }
22 use overload ( '""' => \&toString );
23 use overload ( 'bool' => sub { 0 } );
24 use overload ( '0+' => sub { 0 } );
26 sub toString { 'false' }
29 use vars qw/%_class_map/;
31 sub register_class_hint {
35 $_class_map{$args{hint}} = \%args;
36 $_class_map{$args{name}} = \%args;
40 my ($class, $json) = @_;
42 if (!defined($json)) {
46 #$json =~ s/\/\/.+$//gmo; # remove C++ comments
47 $json =~ s/(?<!\\)\$/\\\$/gmo; # fixup $ for later
48 $json =~ s/(?<!\\)\@/\\\@/gmo; # fixup @ for later
51 my $casting_depth = 0;
54 while ($json =~ s/^\s* (
57 -?\d+\.?\d* | # number literal
58 "(?:(?:\\[\"])|[^\"])*" | # string literal
59 (?:\/\*.+?\*\/) | # C comment
63 : | # object key-value sep
71 if ($element eq 'null') {
72 $output .= ' undef() ';
74 } elsif ($element =~ /^\/\*--\s*S\w*?\s+(\w+)\s*--\*\/$/) {
76 if (exists $_class_map{$hint}) {
77 $casts[$casting_depth] = $hint;
81 } elsif ($element =~ /^\/\*/) {
83 } elsif ($element =~ /^\d/) {
84 $output .= "do { JSON::number::new($element) }";
86 } elsif ($element eq '{' or $element eq '[') {
88 } elsif ($element eq '}' or $element eq ']') {
90 my $hint = $casts[$casting_depth];
91 $casts[$casting_depth] = undef;
92 if (defined $hint and exists $_class_map{$hint}) {
93 $output .= $element . ',"'. $_class_map{$hint}{name} . '")';
96 } elsif ($element eq ':') {
99 } elsif ($element eq 'true') {
100 $output .= 'bless( {}, "JSON::bool::true")';
102 } elsif ($element eq 'false') {
103 $output .= 'bless( {}, "JSON::bool::false")';
114 my ($class, $perl) = @_;
117 if (!defined($perl)) {
119 } elsif (ref($perl) and ref($perl) =~ /^JSON/) {
121 } elsif ( ref($perl) && exists($_class_map{ref($perl)}) ) {
122 $output .= '/*--S '.$_class_map{ref($perl)}{hint}.'--*/';
123 if (lc($_class_map{ref($perl)}{type}) eq 'hash') {
125 $output .= perl2JSON(undef,\%hash);
126 } elsif (lc($_class_map{ref($perl)}{type}) eq 'array') {
128 $output .= perl2JSON(undef,\@array);
130 $output .= '/*--E '.$_class_map{ref($perl)}{hint}.'--*/';
131 } elsif (ref($perl) and ref($perl) =~ /HASH/) {
134 for my $key (sort keys %$perl) {
135 $output .= ',' if ($c);
137 $output .= perl2JSON(undef,$key).':'.perl2JSON(undef,$$perl{$key});
141 } elsif (ref($perl) and ref($perl) =~ /ARRAY/) {
144 for my $part (@$perl) {
145 $output .= ',' if ($c);
147 $output .= perl2JSON(undef,$part);
152 $perl =~ s/\\/\\\\/sgo;
153 $perl =~ s/"/\\"/sgo;
154 $perl =~ s/\t/\\t/sgo;
155 $perl =~ s/\f/\\f/sgo;
156 $perl =~ s/\r/\\r/sgo;
157 $perl =~ s/\n/\\n/sgo;
158 $output = '"'.$perl.'"';
165 sub perl2prettyJSON {
166 my ($class, $perl, $nospace) = @_;
170 if (!defined($perl)) {
172 } elsif (ref($perl) and ref($perl) =~ /^JSON/) {
174 } elsif ( ref($perl) && exists($_class_map{ref($perl)}) ) {
177 $output .= " "x$depth;
178 $output .= '/*--S '.$_class_map{ref($perl)}{hint}."--*/ ";
179 if (lc($_class_map{ref($perl)}{type}) eq 'hash') {
181 $output .= perl2prettyJSON(\%hash,undef,1);
182 } elsif (lc($_class_map{ref($perl)}{type}) eq 'array') {
184 $output .= perl2prettyJSON(\@array,undef,1);
186 #$output .= " "x$depth;
187 $output .= ' /*--E '.$_class_map{ref($perl)}{hint}.'--*/';
189 } elsif (ref($perl) and ref($perl) =~ /HASH/) {
191 $output .= " "x$depth unless ($nospace);
195 for my $key (sort keys %$perl) {
196 $output .= ",\n" if ($c);
198 $output .= perl2prettyJSON($key)." : ".perl2prettyJSON($$perl{$key}, undef, 1);
203 $output .= " "x$depth;
206 } elsif (ref($perl) and ref($perl) =~ /ARRAY/) {
208 $output .= " "x$depth unless ($nospace);
212 for my $part (@$perl) {
213 $output .= ",\n" if ($c);
215 $output .= perl2prettyJSON($part);
220 $output .= " "x$depth;
224 $perl =~ s/\\/\\\\/sgo;
225 $perl =~ s/"/\\"/sgo;
226 $perl =~ s/\t/\\t/sgo;
227 $perl =~ s/\f/\\f/sgo;
228 $perl =~ s/\r/\\r/sgo;
229 $perl =~ s/\n/\\n/sgo;
230 $output .= " "x$depth unless($nospace);
231 $output .= '"'.$perl.'"';