|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2008-09-04 00:32 UTC] steven at acko dot net
Description:
------------
When json_decode() is given certain invalid JSON strings, it will return
the literal string as the result, rather than returning NULL.
Note: in #38680, the decision was made to allow json_decode() to accept
literal basic types (strings, ints, ...) even though this is not allowed
by RFC 4627 (which only allows objects/arrays). This bug report is
different because even under the PHP interpretation of JSON, these
strings can not be considered valid, and trivial variations on them do
in fact throw an error as expected.
(The non-standard behaviour introduced in #38680 is not documented at
all by the way, which is kind of ironic given the numerous issues that
have 'go read the spec' as the answer)
Reproduce code:
---------------
var_dump(json_decode("'invalid json'"));
var_dump(json_decode('invalid json'));
var_dump(json_decode(' {'));
var_dump(json_decode(' ['));
Expected result:
----------------
NULL
NULL
NULL
NULL
Actual result:
--------------
string(14) "'invalid json'"
string(12) "invalid json"
string(2) " {"
string(2) " ["
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Fri Oct 24 13:00:02 2025 UTC |
Please clarify the bogus classification. The following each returns NULL, as expected: var_dump(json_decode('[')); // unmatched bracket var_dump(json_decode('{')); // unmatched brace var_dump(json_decode('{}}')); // unmatched brace var_dump(json_decode('{error error}')); // invalid object key/value notation var_dump(json_decode('["\"]')); // unclosed string var_dump(json_decode('[" \x "]')); // invalid escape code Yet the following each returns the literal argument as a string: var_dump(json_decode(' [')); var_dump(json_decode(' {')); var_dump(json_decode(' {}}')); var_dump(json_decode(' {error error}')); var_dump(json_decode('"\"')); var_dump(json_decode('" \x "')); Please examine the examples closely: they are all meaningless, invalid JSON. Even under the most widely stretched definition of JSON, the above is not JSON encoded data. Yet json_decode() arbitarily returns /some of it/ as a string... and in a way that looks suspiciously like a bad parser implementation. If this was merely a case of json_decode() returning /all/ invalid json as is, then it could be classified as an implementation quirk. But because of how inconsistent it is now, you can't say that it is by design or following any kind of spec. E.g. how would you currently see if json_decode() succeeded or not?@Iliaa: Could this bug be re-evaluated or a more detailed explaination as of why the docs sometimes note that "NULL" is returned on invalid json, and why sometimes json_decode() returns the string instead? If the function returns "whatever" then the docs should be updated to tell the user to not rely on what is returned by json_decode at all. ;-) I double-checked some of Steve's examples on jsonlint.com (which is in most docs cited as the reference validator for json data) and they all show up as "invalid". I also build the most recent 5.2.7 snapshot: ./configure --disable-all --enable-json till@till-laptop:~/php5.2-200811171330$ ./sapi/cli/php test-45989.php string(14) "'invalid json'" string(12) "invalid json" string(2) " {" string(2) " [" till@till-laptop:~/php5.2-200811171330$ ./sapi/cli/php --ini Configuration File (php.ini) Path: /usr/local/lib Loaded Configuration File: (none) Scan for additional .ini files in: (none) Additional .ini files parsed: (none) till@till-laptop:~/php5.2-200811171330$ ./sapi/cli/php -m [PHP Modules] date json Reflection standard [Zend Modules] I'm gonna write a test and send it to QA too.Just to add to this: I know that the function is not supposed to be a JSON validator, but it's supposed to return the string as is -- in case it's a literal type, but why does it in some cases return "null" then? For example: $bad_json = "{ 'bar': 'baz' }"; json_decode($bad_json); // null I know this is "probably" an edge-case but $bad_json could be my own /valid/ string -- not valid JSON. Because a string could look like anything. Point well taken, I'm passing in a pretty /funky/ looking string. But instead of "NULL", json_decode should return the string as-is. That is, according to the documentation, a bug. ;-) Lots of people also seemed to rely on json_decode as a json validator. Which is -- once you understand the subtle differences -- not the case. The case should be made for either one though.The JSON spec states: " A JSON text is a sequence of tokens. The set of tokens includes six structural characters, strings, numbers, and three literal names. A JSON text is a serialized object or array. " So, in order to maintain compliance, PHP must also support non-objects/arrays as input properly. If I understand your patch correctly: If the input is json_decode("null"); the output would be NULL (I saw no test case for null input in the patch itself). We would have no way of knowing a problem exists if one were to have an input of json_decode('[');. Can't this function throw an exception on failure? Failing that,could we at least get a PHP warning? Otherwise it will be impossible to full rely on this function in the case where null is the actual input...