--- JSON-XS/XS.pm 2013/06/27 11:45:17 1.140 +++ JSON-XS/XS.pm 2013/10/29 00:06:40 1.145 @@ -103,24 +103,16 @@ use common::sense; -our $VERSION = 2.34; +our $VERSION = '3.0'; our @ISA = qw(Exporter); -our @EXPORT = qw(encode_json decode_json to_json from_json); - -sub to_json($) { - require Carp; - Carp::croak ("JSON::XS::to_json has been renamed to encode_json, either downgrade to pre-2.0 versions of JSON::XS or rename the call"); -} - -sub from_json($) { - require Carp; - Carp::croak ("JSON::XS::from_json has been renamed to decode_json, either downgrade to pre-2.0 versions of JSON::XS or rename the call"); -} +our @EXPORT = qw(encode_json decode_json); use Exporter; use XSLoader; +use Types::Serialiser (); + =head1 FUNCTIONAL INTERFACE The following convenience methods are provided by this module. They are @@ -151,15 +143,6 @@ Except being faster. -=item $is_boolean = JSON::XS::is_bool $scalar - -Returns true if the passed scalar represents either JSON::XS::true or -JSON::XS::false, two constants that act like C<1> and C<0>, respectively -and are used to represent JSON C and C values in Perl. - -See MAPPING, below, for more information on how JSON values are mapped to -Perl. - =back @@ -669,22 +652,14 @@ =item $json_text = $json->encode ($perl_scalar) -Converts the given Perl data structure (a simple scalar or a reference -to a hash or array) to its JSON representation. Simple scalars will be -converted into JSON string or number sequences, while references to arrays -become JSON arrays and references to hashes become JSON objects. Undefined -Perl values (e.g. C) become JSON C values. Neither C -nor C values will be generated. +Converts the given Perl value or data structure to its JSON +representation. Croaks on error. =item $perl_scalar = $json->decode ($json_text) The opposite of C: expects a JSON text and tries to parse it, returning the resulting simple scalar or reference. Croaks on error. -JSON numbers and strings become simple Perl scalars. JSON arrays become -Perl arrayrefs and JSON objects become Perl hashrefs. C becomes -C<1>, C becomes C<0> and C becomes C. - =item ($perl_scalar, $characters) = $json->decode_prefix ($json_text) This works like the C method, but instead of raising an exception @@ -693,8 +668,7 @@ so far. This is useful if your JSON texts are not delimited by an outer protocol -(which is not the brightest thing to do in the first place) and you need -to know where the JSON text ends. +and you need to know where the JSON text ends. JSON::XS->new->decode_prefix ("[1] the tail") => ([], 3) @@ -798,10 +772,10 @@ =head2 LIMITATIONS All options that affect decoding are supported, except -C. The reason for this is that it cannot be made to -work sensibly: JSON objects and arrays are self-delimited, i.e. you can concatenate -them back to back and still decode them perfectly. This does not hold true -for JSON numbers, however. +C. The reason for this is that it cannot be made to work +sensibly: JSON objects and arrays are self-delimited, i.e. you can +concatenate them back to back and still decode them perfectly. This does +not hold true for JSON numbers, however. For example, is the string C<1> a single JSON number, or is it simply the start of C<12>? Or is C<12> a single JSON number, or the concatenation @@ -1004,15 +978,31 @@ =item true, false -These JSON atoms become C and C, -respectively. They are overloaded to act almost exactly like the numbers -C<1> and C<0>. You can check whether a scalar is a JSON boolean by using -the C function. +These JSON atoms become C and +C, respectively. They are overloaded to act +almost exactly like the numbers C<1> and C<0>. You can check whether +a scalar is a JSON boolean by using the C +function (after C, of course). =item null A JSON null atom becomes C in Perl. +=item shell-style comments (C<< # I >>) + +As a nonstandard extension to the JSON syntax that is enabled by the +C setting, shell-style comments are allowed. They can start +anywhere outside strings and go till the end of the line. + +=item tagged values (C<< (I)I >>). + +Another nonstandard extension to the JSON syntax, enabled with the +C setting, are tagged values. In this implementation, the +I must be a perl package/class name encoded as a JSON string, and the +I must be a JSON array encoding optional constructor arguments. + +See "OBJECT SERIALISATION", below, for details. + =back @@ -1026,15 +1016,13 @@ =item hash references -Perl hash references become JSON objects. As there is no inherent ordering -in hash keys (or JSON objects), they will usually be encoded in a -pseudo-random order that can change between runs of the same program but -stays generally the same within a single run of a program. JSON::XS can -optionally sort the hash keys (determined by the I flag), so -the same datastructure will serialise to the same JSON text (given same -settings and version of JSON::XS), but this incurs a runtime overhead -and is only rarely useful, e.g. when you want to compare some JSON text -against another for equality. +Perl hash references become JSON objects. As there is no inherent +ordering in hash keys (or JSON objects), they will usually be encoded +in a pseudo-random order. JSON::XS can optionally sort the hash keys +(determined by the I flag), so the same datastructure will +serialise to the same JSON text (given same settings and version of +JSON::XS), but this incurs a runtime overhead and is only rarely useful, +e.g. when you want to compare some JSON text against another for equality. =item array references @@ -1044,23 +1032,26 @@ Other unblessed references are generally not allowed and will cause an exception to be thrown, except for references to the integers C<0> and -C<1>, which get turned into C and C atoms in JSON. You can -also use C and C to improve readability. +C<1>, which get turned into C and C atoms in JSON. + +Since C uses the boolean model from L, you +can also C and then use C +and C to improve readability. - encode_json [\0, JSON::XS::true] # yields [false,true] + use Types::Serialiser; + encode_json [\0, Types::Serialiser::true] # yields [false,true] -=item JSON::XS::true, JSON::XS::false +=item Types::Serialiser::true, Types::Serialiser::false -These special values become JSON true and JSON false values, -respectively. You can also use C<\1> and C<\0> directly if you want. +These special values from the L module become JSON true +and JSON false values, respectively. You can also use C<\1> and C<\0> +directly if you want. =item blessed objects -Blessed objects are not directly representable in JSON. See the -C and C methods on various options on -how to deal with this: basically, you can choose between throwing an -exception, encoding the reference as if it weren't blessed, or provide -your own serialiser method. +Blessed objects are not directly representable in JSON, but C +allows various ways of handling objects. See "OBJECT SERIALISATION", +below, for details. =item simple scalars @@ -1107,6 +1098,107 @@ =back +=head2 OBJECT SERIALISATION + +As JSON cannot directly represent Perl objects, you have to choose between +a pure JSON representation (without the ability to deserialise the object +automatically again), and a nonstandard extension to the JSON syntax, +tagged values. + +=head3 SERIALISATION + +What happens when C encounters a Perl object depends on the +C, C and C settings, which are +used in this order: + +=over 4 + +=item 1. C is enabled and object has a C method. + +In this case, C uses the L object +serialisation protocol to create a tagged JSON value, using a nonstandard +extension to the JSON syntax. + +This works by invoking the C method on the object, with the first +argument being the object to serialise, and the second argument being the +constant string C to distinguish it from other serialisers. + +The C method can return any number of values (i.e. zero or +more). These values and the paclkage/classname of the object will then be +encoded as a tagged JSON value in the following format: + + ("classname")[FREEZE return values...] + +For example, the hypothetical C C method might use the +objects C and C members to encode the object: + + sub My::Object::FREEZE { + my ($self, $serialiser) = @_; + + ($self->{type}, $self->{id}) + } + +=item 2. C is enabled and object has a C method. + +In this case, the C method of the object is invoked in scalar +context. It must return a single scalar that can be directly encoded into +JSON. This scalar replaces the object in the JSON text. + +For example, the following C method will convert all L +objects to JSON strings when serialised. The fatc that these values +originally were L objects is lost. + + sub URI::TO_JSON { + my ($uri) = @_; + $uri->as_string + } + +=item 3. C is enabled. + +The object will be serialised as a JSON null value. + +=item 4. none of the above + +If none of the settings are enabled or the respective methods are missing, +C throws an exception. + +=back + +=head3 DESERIALISATION + +For deserialisation there are only two cases to consider: either +nonstandard tagging was used, in which case C decides, +or objects cannot be automatically be deserialised, in which +case you can use postprocessing or the C or +C callbacks to get some real objects our of +your JSON. + +This section only considers the tagged value case: I a tagged JSON object +is encountered during decoding and C is disabled, a parse +error will result (as if tagged values were not part of the grammar). + +If C is enabled, C will look up the C method +of the package/classname used during serialisation. If there is no such +method, the decoding will fail with an error. + +Otherwise, the C method is invoked with the classname as first +argument, the constant string C as second argument, and all the +values from the JSON array (the values originally returned by the +C method) as remaining arguments. + +The method must then return the object. While technically you can return +any Perl scalar, you might have to enable the C setting to +make that work in all cases, so better return an actual blessed reference. + +As an example, let's implement a C function that regenerates the +C from the C example earlier: + + sub My::Object::THAW { + my ($class, $serialiser, $type, $id) = @_; + + $class->new (type => $type, id => $id) + } + =head1 ENCODING/CODESET FLAG NOTES @@ -1438,6 +1530,14 @@ security right). +=head1 INTEROPERABILITY WITH OTHER MODULES + +C uses the L module to provide boolean +constants. That means that the JSON true and false values will be +comaptible to true and false values of iother modules that do the same, +such as L and L. + + =head1 THREADS This module is I guaranteed to be thread safe and there are no @@ -1477,29 +1577,18 @@ =cut -our $true = do { bless \(my $dummy = 1), "JSON::XS::Boolean" }; -our $false = do { bless \(my $dummy = 0), "JSON::XS::Boolean" }; - -sub true() { $true } -sub false() { $false } +BEGIN { + *true = \$Types::Serialiser::true; + *true = \&Types::Serialiser::true; + *false = \$Types::Serialiser::false; + *false = \&Types::Serialiser::false; + *is_bool = \&Types::Serialiser::is_bool; -sub is_bool($) { - UNIVERSAL::isa $_[0], "JSON::XS::Boolean" -# or UNIVERSAL::isa $_[0], "JSON::Literal" + *JSON::XS::Boolean:: = *Types::Serialiser::Boolean::; } XSLoader::load "JSON::XS", $VERSION; -package JSON::XS::Boolean; - -use overload - "0+" => sub { ${$_[0]} }, - "++" => sub { $_[0] = ${$_[0]} + 1 }, - "--" => sub { $_[0] = ${$_[0]} - 1 }, - fallback => 1; - -1; - =head1 SEE ALSO The F command line utility for quick experiments. @@ -1511,3 +1600,5 @@ =cut +1 +