1 package OpenSRF::Utils::JSON;
2 use strict; use warnings;
5 our $parser = JSON::XS->new;
6 $parser->ascii(1); # output \u escaped strings for any char with a value over 127
7 $parser->allow_nonref(1); # allows non-reference values to equate to themselves (see perldoc)
10 our $JSON_CLASS_KEY = '__c';
11 our $JSON_PAYLOAD_KEY = '__p';
16 OpenSRF::Utils::JSON - Bucket-o-Routines for JSON
20 C<O::U::JSON> is a functional-style package which exports nothing. All
21 calls to routines must use the fully-qualified name, and expect an
24 OpenSRF::Utils::JSON->JSON2perl($string);
26 Most routines are straightforward data<->JSON transformation wrappers
27 around L<JSON::XS>, but some (like L</register_class_hint>) provide
28 OpenSRF functionality.
32 =head2 register_class_hint
36 sub register_class_hint {
37 my ($pkg, %args) = @_;
38 $_class_map{hints}{$args{hint}} = \%args;
39 $_class_map{classes}{$args{name}} = \%args;
47 my ($pkg, $hint) = @_;
48 return $_class_map{hints}{$hint}{name}
56 my ($pkg, $class) = @_;
57 return $_class_map{classes}{$class}{hint}
65 my( $pkg, $string ) = @_;
66 my $perl = $pkg->rawJSON2perl($string);
67 return $pkg->JSONObject2Perl($perl);
75 my( $pkg, $obj ) = @_;
76 my $json = $pkg->perl2JSONObject($obj);
77 return $pkg->rawPerl2JSON($json);
82 Internal routine used by L</JSON2Perl>. Wrapper around
88 my ($class, $json) = @_;
89 return undef unless defined $json and $json !~ /^\s*$/o;
90 return $parser->decode($json);
95 Internal routine used by L</Perl2JSON>. Wrapper around
101 my ($class, $perl) = @_;
102 return $parser->encode($perl);
105 =head2 JSONObject2Perl
109 sub JSONObject2Perl {
110 my ($pkg, $obj) = @_;
112 if( $ref eq 'HASH' ) {
113 if( defined($obj->{$JSON_CLASS_KEY})) {
114 my $class = $obj->{$JSON_CLASS_KEY};
117 if( $obj = $pkg->JSONObject2Perl($obj->{$JSON_PAYLOAD_KEY}) ) {
118 $class = $pkg->lookup_class($class) || $class;
119 return bless(\$obj, $class) unless ref($obj);
120 return bless($obj, $class);
124 for my $k (keys %$obj) {
125 $obj->{$k} = $pkg->JSONObject2Perl($obj->{$k})
126 unless ref($obj->{$k}) eq 'JSON::XS::Boolean';
128 } elsif( $ref eq 'ARRAY' ) {
129 for my $i (0..scalar(@$obj) - 1) {
130 $obj->[$i] = $pkg->JSONObject2Perl($obj->[$i])
131 unless ref($obj->[$i]) eq 'JSON::XS::Boolean';
137 =head2 perl2JSONObject
141 sub perl2JSONObject {
146 return $obj unless $ref;
148 return $obj if $ref eq 'JSON::XS::Boolean';
151 if(UNIVERSAL::isa($obj, 'HASH')) {
153 $newobj->{$_} = $class->perl2JSONObject($obj->{$_}) for (keys %$obj);
154 } elsif(UNIVERSAL::isa($obj, 'ARRAY')) {
156 $newobj->[$_] = $class->perl2JSONObject($obj->[$_]) for(0..scalar(@$obj) - 1);
159 if($ref ne 'HASH' and $ref ne 'ARRAY') {
160 $ref = $class->lookup_hint($ref) || $ref;
161 $newobj = {$JSON_CLASS_KEY => $ref, $JSON_PAYLOAD_KEY => $newobj};
169 Wrapper for JSON::XS::true. J::X::true and J::X::false, according to
170 its documentation, "are JSON atoms become JSON::XS::true and
171 JSON::XS::false, respectively. They are overloaded to act almost
172 exactly like the numbers 1 and 0"
176 sub true { return $parser->true }
184 sub false { return $parser->false }