--- JSON-XS/XS.pm 2008/05/08 15:33:06 1.104 +++ JSON-XS/XS.pm 2010/01/19 00:31:13 1.128 @@ -39,7 +39,7 @@ Beginning with version 2.0 of the JSON module, when both JSON and JSON::XS are installed, then JSON will fall back on JSON::XS (this can be -overriden) with no overhead due to emulation (by inheritign constructor +overridden) with no overhead due to emulation (by inheriting constructor and methods). If JSON::XS is not available, it will fall back to the compatible JSON::PP module as backend, so using JSON instead of JSON::XS gives you a portable JSON API that can be fast when you need and doesn't @@ -51,8 +51,6 @@ their maintainers are unresponsive, gone missing, or not listening to bug reports for other reasons. -See COMPARISON, below, for a comparison to some other JSON modules. - See MAPPING, below, on how JSON::XS maps perl values to JSON values and vice versa. @@ -67,7 +65,7 @@ =item * round-trip integrity -When you serialise a perl data structure using only datatypes supported +When you serialise a perl data structure using only data types supported by JSON, the deserialised data structure is identical on the Perl level. (e.g. the string "2.0" doesn't suddenly become "2" just because it looks like a number). There minor I exceptions to this, read the MAPPING @@ -86,13 +84,13 @@ =item * simple to use -This module has both a simple functional interface as well as an objetc +This module has both a simple functional interface as well as an object oriented interface interface. =item * reasonably versatile output formats You can choose between the most compact guaranteed-single-line format -possible (nice for simple line-based protocols), a pure-ascii format +possible (nice for simple line-based protocols), a pure-ASCII format (for when your transport is not 8-bit clean, still supports the whole Unicode range), or a pretty-printed format (for when you want to read that stuff). Or you can combine those features in whatever way you like. @@ -103,9 +101,9 @@ package JSON::XS; -use strict; +use common::sense; -our $VERSION = '2.2'; +our $VERSION = '2.28'; our @ISA = qw(Exporter); our @EXPORT = qw(encode_json decode_json to_json from_json); @@ -139,7 +137,7 @@ $json_text = JSON::XS->new->utf8->encode ($perl_scalar) -except being faster. +Except being faster. =item $perl_scalar = decode_json $json_text @@ -151,7 +149,7 @@ $perl_scalar = JSON::XS->new->utf8->decode ($json_text) -except being faster. +Except being faster. =item $is_boolean = JSON::XS::is_bool $scalar @@ -199,7 +197,7 @@ exist. =item 4. A "Unicode String" is simply a string where each character can be -validly interpreted as a Unicode codepoint. +validly interpreted as a Unicode code point. If you have UTF-8 encoded data, it is no longer a Unicode string, but a Unicode string encoded in UTF-8, giving you a binary string. @@ -445,6 +443,8 @@ This setting has no effect when decoding JSON texts. +This setting has currently no effect on tied hashes. + =item $json = $json->allow_nonref ([$enable]) =item $enabled = $json->get_allow_nonref @@ -703,19 +703,25 @@ =head1 INCREMENTAL PARSING -[This section and the API it details is still EXPERIMENTAL] - In some cases, there is the need for incremental parsing of JSON texts. While this module always has to keep both JSON text and resulting Perl data structure in memory at one time, it does allow you to parse a JSON stream incrementally. It does so by accumulating text until it has a full JSON object, which it then can decode. This process is similar to -using C to see if a full JSON object is available, but is -much more efficient (JSON::XS will only attempt to parse the JSON text -once it is sure it has enough text to get a decisive result, using a very -simple but truly incremental parser). +using C to see if a full JSON object is available, but +is much more efficient (and can be implemented with a minimum of method +calls). + +JSON::XS will only attempt to parse the JSON text once it is sure it +has enough text to get a decisive result, using a very simple but +truly incremental parser. This means that it sometimes won't stop as +early as the full parser, for example, it doesn't detect parenthese +mismatches. The only thing it guarantees is that it starts decoding as +soon as a syntactically valid JSON text has been seen. This means you need +to set resource limits (e.g. C) to ensure the parser will stop +parsing in the presence if syntax errors. -The following two methods deal with this. +The following methods implement this incremental parser. =over 4 @@ -763,10 +769,23 @@ =item $json->incr_skip -This will reset the state of the incremental parser and will remove the -parsed text from the input buffer. This is useful after C -died, in which case the input buffer and incremental parser state is left -unchanged, to skip the text parsed so far and to reset the parse state. +This will reset the state of the incremental parser and will remove +the parsed text from the input buffer so far. This is useful after +C died, in which case the input buffer and incremental parser +state is left unchanged, to skip the text parsed so far and to reset the +parse state. + +The difference to C is that only text until the parse error +occured is removed. + +=item $json->incr_reset + +This completely resets the incremental parser, that is, after this call, +it will be as if the parser had never parsed anything. + +This is useful if you want to repeatedly parse JSON objects and want to +ignore any trailing data, which means you have to reset the parser after +each successful decode. =back @@ -1169,6 +1188,71 @@ =back +=head2 JSON and ECMAscript + +JSON syntax is based on how literals are represented in javascript (the +not-standardised predecessor of ECMAscript) which is presumably why it is +called "JavaScript Object Notation". + +However, JSON is not a subset (and also not a superset of course) of +ECMAscript (the standard) or javascript (whatever browsers actually +implement). + +If you want to use javascript's C function to "parse" JSON, you +might run into parse errors for valid JSON texts, or the resulting data +structure might not be queryable: + +One of the problems is that U+2028 and U+2029 are valid characters inside +JSON strings, but are not allowed in ECMAscript string literals, so the +following Perl fragment will not output something that can be guaranteed +to be parsable by javascript's C: + + use JSON::XS; + + print encode_json [chr 0x2028]; + +The right fix for this is to use a proper JSON parser in your javascript +programs, and not rely on C (see for example Douglas Crockford's +F parser). + +If this is not an option, you can, as a stop-gap measure, simply encode to +ASCII-only JSON: + + use JSON::XS; + + print JSON::XS->new->ascii->encode ([chr 0x2028]); + +Note that this will enlarge the resulting JSON text quite a bit if you +have many non-ASCII characters. You might be tempted to run some regexes +to only escape U+2028 and U+2029, e.g.: + + # DO NOT USE THIS! + my $json = JSON::XS->new->utf8->encode ([chr 0x2028]); + $json =~ s/\xe2\x80\xa8/\\u2028/g; # escape U+2028 + $json =~ s/\xe2\x80\xa9/\\u2029/g; # escape U+2029 + print $json; + +Note that I: the above only works for U+2028 and +U+2029 and thus only for fully ECMAscript-compliant parsers. Many existing +javascript implementations, however, have issues with other characters as +well - using C naively simply I cause problems. + +Another problem is that some javascript implementations reserve +some property names for their own purposes (which probably makes +them non-ECMAscript-compliant). For example, Iceweasel reserves the +C<__proto__> property name for it's own purposes. + +If that is a problem, you could parse try to filter the resulting JSON +output for these property strings, e.g.: + + $json =~ s/"__proto__"\s*:/"__proto__renamed":/g; + +This works because C<__proto__> is not valid outside of strings, so every +occurence of C<"__proto__"\s*:> must be a string used as property name. + +If you know of other incompatibilities, please let me know. + + =head2 JSON and YAML You often hear that JSON is a subset of YAML. This is, however, a mass @@ -1186,12 +1270,12 @@ This will I generate JSON texts that also parse as valid YAML. Please note that YAML has hardcoded limits on (simple) object key lengths that JSON doesn't have and also has different and incompatible -unicode handling, so you should make sure that your hash keys are -noticeably shorter than the 1024 "stream characters" YAML allows and that -you do not have characters with codepoint values outside the Unicode BMP -(basic multilingual page). YAML also does not allow C<\/> sequences in -strings (which JSON::XS does not I generate, but other JSON -generators might). +unicode character escape syntax, so you should make sure that your hash +keys are noticeably shorter than the 1024 "stream characters" YAML allows +and that you do not have characters with codepoint values outside the +Unicode BMP (basic multilingual page). YAML also does not allow C<\/> +sequences in strings (which JSON::XS does not I generate, but +other JSON generators might). There might be other incompatibilities that I am not aware of (or the YAML specification has been changed yet again - it does so quite often). In @@ -1220,6 +1304,12 @@ real compatibility for many I and trying to silence people who point out that it isn't true. +Addendum/2009: the YAML 1.2 spec is still incomaptible with JSON, even +though the incompatibilities have been documented (and are known to +Brian) for many years and the spec makes explicit claims that YAML is a +superset of JSON. It would be so easy to fix, but apparently, bullying and +corrupting userdata is so much easier. + =back @@ -1324,11 +1414,11 @@ If you are using JSON::XS to return packets to consumption by JavaScript scripts in a browser you should have a look at -L to see whether -you are vulnerable to some common attack vectors (which really are browser -design bugs, but it is still you who will have to deal with it, as major -browser developers care only for features, not about getting security -right). +L to +see whether you are vulnerable to some common attack vectors (which really +are browser design bugs, but it is still you who will have to deal with +it, as major browser developers care only for features, not about getting +security right). =head1 THREADS