I added a 3rd regex to the json_decode_nice function by "colin.mollenhour.com" to handle a trailing comma in json definition.
<?php
// http://www.php.net/manual/en/function.json-decode.php#95782
function json_decode_nice($json, $assoc = FALSE){
$json = str_replace(array("\n","\r"),"",$json);
$json = preg_replace('/([{,]+)(\s*)([^"]+?)\s*:/','$1"$3":',$json);
$json = preg_replace('/(,)\s*}$/','}',$json);
return json_decode($json,$assoc);
}
?>
Example:
<?php
$dat_json = <<<EOF
{
"foo" : "bam",
"bar" : "baz",
}
EOF;
$dat_array = json_decode_nice( $dat_json );
var_dump ( $dat_json, $dat_array );
/* RESULTS:
string(35) "{
"foo" : "bam",
"bar" : "baz",
}"
array(2) {
["foo"]=>
string(3) "bam"
["bar"]=>
string(3) "baz"
}
*/
?>
json_decode
(PHP 5 >= 5.2.0, PECL json >= 1.2.0)
json_decode — Convertește într-o variabilă un șir reprezentat JSON
Descrierea
$json
[, bool $assoc = false
[, int $depth = 512
[, int $options = 0
]]] )Preia un șir de caractere reprezentat JSON și îl convertește într-o variabilă PHP.
Parametri
-
json -
Șirul (string) reprezentat
jsoncare trebuie convertit.Această funcție operează doar cu date codificate în UTF-8.
-
assoc -
Dacă specificați
TRUE, obiectul va fi convertit într-un array asociativ. -
depth -
Limita adâncimii de imbricare specificată de utilizator.
-
options -
Masca de biți a opțiunilor de decodificare JSON. în prezent este susținută doar
JSON_BIGINT_AS_STRING(în mod implicit numerele întregi mari se transformă în numere cu virgulă flotantă)Această modificare există în versiunea de dezvoltare a PHP și probabil va exista după 5.3.
Valorile întoarse
Întoarce valoarea codificată în json cu tipul PHP
corespunzător. Valorile true, false și
null (indiferent de tipul caracterelor - minuscule sau
majuscule) sunt întoarse ca TRUE, FALSE și NULL respectiv. NULL este
întors dacă parametrul json nu poate fi decodificat
sau dacă datele pentru codificare sunt mai adânci decât limita de imbricare.
Exemple
Example #1 json_decode() exemplu
<?php
$json = '{"a":1,"b":2,"c":3,"d":4,"e":5}';
var_dump(json_decode($json));
var_dump(json_decode($json, true));
?>
Exemplul de mai sus va afișa:
object(stdClass)#1 (5) {
["a"] => int(1)
["b"] => int(2)
["c"] => int(3)
["d"] => int(4)
["e"] => int(5)
}
array(5) {
["a"] => int(1)
["b"] => int(2)
["c"] => int(3)
["d"] => int(4)
["e"] => int(5)
}
Example #2 Un alt exemplu
<?php
$json = '{"foo-bar": 12345}';
$obj = json_decode($json);
print $obj->{'foo-bar'}; // 12345
?>
Example #3 greșeli comune la utilizarea json_decode()
<?php
// următoarele stringuri sunt JavaScript valid, dar nu și JSON valid
// denumirea și valoarea trebuie incluse între ghilimele duble
// ghilimelele obișnuite nu sunt valide
$bad_json = "{ 'bar': 'baz' }";
json_decode($bad_json); // null
// denumirea trebuie inclusă între ghilimele duble
$bad_json = '{ bar: "baz" }';
json_decode($bad_json); // null
// virgula la sfârșit nu este permisă
$bad_json = '{ bar: "baz", }';
json_decode($bad_json); // null
?>
Example #4 Erori ale depth
<?php
// Codifică datele.
$json = json_encode(
array(
1 => array(
'English' => array(
'One',
'January'
),
'French' => array(
'Une',
'Janvier'
)
)
)
);
// Definește erorile.
$json_errors = array(
JSON_ERROR_NONE => 'No error has occurred',
JSON_ERROR_DEPTH => 'The maximum stack depth has been exceeded',
JSON_ERROR_CTRL_CHAR => 'Control character error, possibly incorrectly encoded',
JSON_ERROR_SYNTAX => 'Syntax error',
);
// Arată erorile pentru diferite adâncimi.
foreach(range(4, 3, -1) as $depth) {
var_dump(json_decode($json, True, $depth));
echo 'Last error : ', $json_errors[json_last_error()], PHP_EOL, PHP_EOL;
}
?>
Exemplul de mai sus va afișa:
array(1) {
[1]=>
array(2) {
["English"]=>
array(2) {
[0]=>
string(3) "One"
[1]=>
string(7) "January"
}
["French"]=>
array(2) {
[0]=>
string(3) "Une"
[1]=>
string(7) "Janvier"
}
}
}
Last error : No error has occurred
NULL
Last error : The maximum stack depth has been exceeded
Example #5 json_decode() cu numere întregi mari
<?php
$json = '12345678901234567890';
var_dump(json_decode($json));
var_dump(json_decode($json, false, 512, JSON_BIGINT_AS_STRING));
?>
Exemplul de mai sus va afișa:
float(1.2345678901235E+19) string(20) "12345678901234567890"
Note
Notă:
Specificația JSON nu este JavaScript, ci un subset al JavaScript.
Notă:
În cazul decodificării cu eșec funcția json_last_error() poate fi utilizată pentru a determina natura exactă a erorii.
Istoria schimbărilor
| Versiunea | Descriere |
|---|---|
| Viitor |
A fost adăugat parametrul options.
|
| 5.3.0 | A fost adăugat parametrul opțional depth.
Limita de imbricare implicită a fost mărită de la 128 la 512. |
| 5.2.3 | Limita de imbricare a fost mărită de la 20 la 128. |
Vedeți de asemenea
- json_encode() - Întoarce o reprezentare JSON pentru valoarea dată
- json_last_error() - Întoarce ultima eroare ce a survenit
Sometime, i need to allow comments in json file. So i wrote a small func to clean comments in a json string before decoding it:
<?php
/**
* Clean comments of json content and decode it with json_decode().
* Work like the original php json_decode() function with the same params
*
* @param string $json The json string being decoded
* @param bool $assoc When TRUE, returned objects will be converted into associative arrays.
* @param integer $depth User specified recursion depth. (>=5.3)
* @param integer $options Bitmask of JSON decode options. (>=5.4)
* @return string
*/
function json_clean_decode($json, $assoc = false, $depth = 512, $options = 0) {
// search and remove comments like /* */ and //
$json = preg_replace("#(/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+/)|([\s\t](//).*)#", '', $json);
if(version_compare(phpversion(), '5.4.0', '>=')) {
$json = json_decode($json, $assoc, $depth, $options);
}
elseif(version_compare(phpversion(), '5.3.0', '>=')) {
$json = json_decode($json, $assoc, $depth);
}
else {
$json = json_decode($json, $assoc);
}
return $json;
}
?>
it seems, that some of the people are not aware, that if you are using json_decode to decode a string it HAS to be a propper json string:
<?php
var_dump(json_encode('Hello'));
var_dump(json_decode('Hello')); // wrong
var_dump(json_decode("Hello")); // wrong
var_dump(json_decode('"Hello"')); // correct
var_dump(json_decode("'Hello'")); // wrong
result:
string(7) ""Hello""
NULL
NULL
string(5) "Hello"
NULL
Make sure you pass in utf8 content, or json_decode may error out and just return a null value. For a particular web service I was using, I had to do the following:
<?php
$contents = file_get_contents($url);
$contents = utf8_encode($contents);
$results = json_decode($contents);
?>
Hope this helps!
When decoding strings from the database, make sure the input was encoded with the correct charset when it was input to the database.
I was using a form to create records in the DB which had a content field that was valid JSON, but it included curly apostrophes. If the page with the form did not have
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
in the head, then the data was sent to the database with the wrong encoding. Then, when json_decode tried to convert the string to an object, it failed every time.
with two lines you can convert your string from JavaScript toSource() (see http://www.w3schools.com/jsref/jsref_toSource.asp) output format to JSON accepted format. this works with subobjects too!
note: toSource() is part of JavaScript 1.3 but only implemented in Mozilla based javascript engines (not Opera/IE/Safari/Chrome).
<?php
$str = '({strvar:"string", number:40, boolvar:true, subobject:{substrvar:"sub string", subsubobj:{deep:"deeply nested"}, strnum:"56"}, false_val:false, false_str:"false"})'; // example javascript object toSource() output
$str = substr($str, 1, strlen($str) - 2); // remove outer ( and )
$str = preg_replace("/([a-zA-Z0-9_]+?):/" , "\"$1\":", $str); // fix variable names
$output = json_decode($str, true);
var_dump($output);
?>
var_dump output:
array(6) {
["strvar"]=>
string(6) "string"
["number"]=>
int(40)
["boolvar"]=>
bool(true)
["subobject"]=>
array(3) {
["substrvar"]=>
string(10) "sub string"
["subsubobj"]=>
array(1) {
["deep"]=>
string(13) "deeply nested"
}
["strnum"]=>
string(2) "56"
}
["false_val"]=>
bool(false)
["false_str"]=>
string(5) "false"
}
hope this saves someone some time.
First of all, since JSON is not native PHP format or even native JavaScript format, everyone who wants to use JSON wisely should carefuly read official documentation. There is a link to it here, in "Introduction" section. Many questions like "it doesn't recognize my strings" and those like previous one (about zip codes) will drop if you will be attentive!
And second. I've found that there is no good, real working example of how to validate string if it is a JSON or not.
There are two ways to make this: parse input string for yourself using regular expressions or anything else, use json_decode to do it for you.
Parsing for yourself is like writing your own compiler, too difficult.
Just testing result of json_decode is not enough because you should test it with NULL, but valid JSON could be like this 'null' and it will evaluate to NULL. So you should use another function - json_last_error. It will return error code of the last encode/decode operation. If no error occured it will be JSON_ERROR_NONE. So here is the function you should use for testing:
<?php
function isValidJson($strJson) {
json_decode($strJson);
return (json_last_error() === JSON_ERROR_NONE);
}
?>
It's so simple, that there is no need to use it and slow down your script with extra delay for function call. Just do it manualy in you code while working with input data:
<?php
//here is my initial string
$sJson = $_POST['json'];
//try to decode it
$json = json_decode($sJson);
if (json_last_error() === JSON_ERROR_NONE) {
//do something with $json. It's ready to use
} else {
//yep, it's not JSON. Log error or alert someone or do nothing
}
?>
For those of you wanting json_decode to be a little more lenient (more like Javascript), here is a wrapper:
<?php
function json_decode_nice($json, $assoc = FALSE){
$json = str_replace(array("\n","\r"),"",$json);
$json = preg_replace('/([{,]+)(\s*)([^"]+?)\s*:/','$1"$3":',$json);
return json_decode($json,$assoc);
}
?>
Some examples of accepted syntax:
<?php
$json = '{a:{b:"c",d:["e","f",0]}}';
$json =
'{
a : {
b : "c",
"d.e.f": "g"
}
}';
?>
If your content needs to have newlines, do this:
<?php
$string = "This
Text
Has
Newlines";
$json = '{withnewlines:'.json_encode($string).'}';
?>
Note: This does not fix trailing commas or single quotes.
[EDIT BY danbrown AT php DOT net: Contains a bugfix provided by (sskaje AT gmail DOT com) on 05-DEC-2012 with the following note.]
Old regexp failed when json like
{aaa:[{a:1},{a:2}]}
Consider that JSON can differ between int and string. So
<?php
var_dump(json_decode('{"foo": 12}'));
// array(1) { ["foo"]=> int(12) }
var_dump(json_decode('{"foo": "12"}'));
// array(1) { ["foo"]=> string(12) }
?>
Numbers that cannot be handled by integer seems to become float casted. This can be a problem if you transfer big numbers like facebook ids over JSON. Either you avoid numbers by cast everything to string before JSON.stringify or you have to use number_format if the value bacome a float value.
<?php
// test
$x = json_decode('{"foo": 123456789012345}');
echo sprintf('%1$f', $x->foo).PHP_EOL;
echo sprintf('%1$u', $x->foo).PHP_EOL;
echo sprintf('%1$s', $x->foo).PHP_EOL;
echo strval($x->foo).PHP_EOL;
echo (string) $x->foo.PHP_EOL;
echo number_format($x->foo, 0, '', '').PHP_EOL;
// output
123456789012345.000000 // printf %f
2249056121 // printf %u
1.2345678901234E+14 // printf %s
1.2345678901234E+14 // strval()
1.2345678901234E+14 // cast (string)
2249056121 // cast (int)
123456789012345 // number_format()
?>
If var_dump produces NULL, you may be experiencing JSONP aka JSON with padding, here's a quick fix...
<?php
//remove padding
$body=preg_replace('/.+?({.+}).+/','$1',$body);
// now, process the JSON string
$result = json_decode($body);
var_dump($result);
?>
In PHP <= 5.1.6 trying to decode an integer value that's > PHP_INT_MAX will result in an intger of PHP_INT_MAX.
In PHP 5.2+ decoding an integer > PHP_INT_MAX will cause a conversion to a float.
Neither behaviour is perfect, capping at PHP_INT_MAX is marginally worse, but the float conversion loses precision.
If you expect to deal with large numbers at all, let alone in JSON, ensure you're using a 64-bit system.
Noted in a comment below is that this function will return NULL when given a simple string.
This is new behavior - see the result in PHP 5.2.4 :
php > var_dump(json_decode('this is a simple string'));
string(23) "this is a simple string"
in PHP 5.3.2 :
php > var_dump(json_decode('this is a simple string'));
NULL
I had several functions that relied on checking the value of a purported JSON string if it didn't decode into an object/array. If you do too, be sure to be aware of this when upgrading to PHP 5.3.
This function will remove trailing commas and encode in utf8, which might solve many people's problems. Someone might want to expand it to also change single quotes to double quotes, and fix other kinds of json breakage.
<?php
function mjson_decode($json)
{
return json_decode(removeTrailingCommas(utf8_encode($json)));
}
function removeTrailingCommas($json)
{
$json=preg_replace('/,\s*([\]}])/m', '$1', $json);
return $json;
}
?>
You can't transport Objects or serialize Classes, json_* replace it bei stdClass!
<?php
$dom = new DomDocument( '1.0', 'utf-8' );
$body = $dom->appendChild( $dom->createElement( "body" ) );
$body->appendChild( $dom->createElement( "forward", "Hallo" ) );
$JSON_STRING = json_encode(
array(
"aArray" => range( "a", "z" ),
"bArray" => range( 1, 50 ),
"cArray" => range( 1, 50, 5 ),
"String" => "Value",
"stdClass" => $dom,
"XML" => $dom->saveXML()
)
);
unset( $dom );
$Search = "XML";
$MyStdClass = json_decode( $JSON_STRING );
// var_dump( "<pre>" , $MyStdClass , "</pre>" );
try {
throw new Exception( "$Search isn't a Instance of 'stdClass' Class by json_decode()." );
if ( $MyStdClass->$Search instanceof $MyStdClass )
var_dump( "<pre>instanceof:" , $MyStdClass->$Search , "</pre>" );
} catch( Exception $ErrorHandle ) {
echo $ErrorHandle->getMessage();
if ( property_exists( $MyStdClass, $Search ) ) {
$dom = new DomDocument( "1.0", "utf-8" );
$dom->loadXML( $MyStdClass->$Search );
$body = $dom->getElementsByTagName( "body" )->item(0);
$body->appendChild( $dom->createElement( "rewind", "Nice" ) );
var_dump( htmlentities( $dom->saveXML(), ENT_QUOTES, 'utf-8' ) );
}
}
?>
json_decode()'s handling of invalid JSON is very flaky, and it is very hard to reliably determine if the decoding succeeded or not. Observe the following examples, none of which contain valid JSON:
The following each returns NULL, as you might expect:
<?php
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 string you passed to it:
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
?>
(this is on PHP 5.2.6)
Reported as a bug, but oddly enough, it was closed as not a bug.
[NOTE BY danbrown AT php DOT net: This was later re-evaluated and it was determined that an issue did in fact exist, and was patched by members of the Development Team. See http://bugs.php.net/bug.php?id=45989 for details.]
I found that even though json_decode() takes UTF-8 strings, it won't parse if a Byte-Order-Mark (BOM) is present.
Also, if you allow your users to edit JSON files, you end up with a mix of ASCII, ISO-8859-1, UTF-8 with and without BOM.
This function prepares a string for the JSON parser by converting it to UTF-8 and removing the BOM if present.
<?php
function prepareJSON($input) {
//This will convert ASCII/ISO-8859-1 to UTF-8.
//Be careful with the third parameter (encoding detect list), because
//if set wrong, some input encodings will get garbled (including UTF-8!)
$imput = mb_convert_encoding($input, 'UTF-8', 'ASCII,UTF-8,ISO-8859-1');
//Remove UTF-8 BOM if present, json_decode() does not like it.
if(substr($input, 0, 3) == pack("CCC", 0xEF, 0xBB, 0xBF)) $input = substr($input, 3);
return $input;
}
//Usage:
$myFile = file_get_contents('somefile.json');
$myDataArr = json_decode(prepareJSON($myFile), true);
?>
There is a problem when passing to json_decode a string with the "\" symbol. It seems to identify it as an escape character and trying to follow it. So sometimes it leads to failed parsing.
It seems that just replacing it with "\\" helps.
<?php
print_r(json_decode(str_replace('\\', '\\\\', '{"name":"/\"}')));
?>
where /\ is the string which doesn't worked.
I thought I would advise you to be careful if using U.S. addresses, particularly five-digit zip codes, with json_encode and json_decode.
The manual states that json_decode($data) will return $data in the appropriate PHP type. But it may not be the type you stored!
In my case, I have some data that might be scalar (e.g. string containing "01234") or might be a json packet (containing multiple zipcodes), and I was calling json_decode on everything.
<?php
$zip = "01234";
$test_zip = json_decode($zip);
echo $zip === $test_zip; // FALSE
?>
Because $test_zip is an integer containing 1234.
When in php 5.2.3, I found that json_decode 4000000000 float value into integer value resulting int(-294967296) from var_dump function
When in php 5.3.x, php correctly returning float(4000000000)
thank you for people creating & upgrading php
Yohan W.
Be aware, when decoding JSON strings, where an empty string is a key, this library replaces the empty string with "_empty_".
So the following code gives an unexpected result:
<?php
var_dump(json_decode('{"":"arbitrary"}'));
?>
The result is as follows:
object(stdClass)#1 (1) {
["_empty_"]=>
string(6) "arbitrary"
}
Any subsequent key named "_empty_" (or "" [the empty string] again) will overwrite the value.
I pulled my hair off for hours trying to get rid of strange backslashes in my incoming JSON-data in POST-pool, making it impossible to decode the incoming JSON-data.
For those of you facing the same problem:
just make sure you disable 'magic_quotes_gpc' in your php.ini and the incoming data will not be pseudo-escaped anymore. Now your incoming JSON-data should just be decoded fine.
Maybe this will help.
json_decode_nice + keep linebreaks:
function json_decode_nice($json, $assoc = TRUE){
$json = str_replace(array("\n","\r"),"\\n",$json);
$json = preg_replace('/([{,]+)(\s*)([^"]+?)\s*:/','$1"$3":',$json);
$json = preg_replace('/(,)\s*}$/','}',$json);
return json_decode($json,$assoc);
}
by phpdoc at badassawesome dot com, I just changed line 2.
If you want to keep the linebreaks just escape the slash.
It was quite hard to figure out the allowed Javascript formats. Some extra remarks:
json_decode() doesn't seem to allow single quotes:
<?php
print_r(json_decode('[0,{"a":"a","b":"b"},2,3]')); //works
print_r(json_decode("[0,{'a':'a','b':'b'},2,3]")); //doesn't work
?>
json_decode() doesn't allow an extra comma in a list of entries:
<?php
print_r(json_decode('[0,1 ]')); //works
print_r(json_decode('[0,1,]')); //doesn't work
?>
(I like to write a comma behind every entry when the entries are spread over several lines.)
json_decode() does allow linefeeds in the data!
?>
I had a JSON string with multiple commas in it without any quotes, which was causing the json_decode to return false.
Once the double quotes were added, everything worked out fine.
A quick:
while(strpos($contents, ',,') !== false) {
$contents = str_replace(',,', ',"",', $contents);
}
solved the problem, and the function worked correctly. If you have tried everything and are still a FALSE return, I suggest trying the JSON validator in another post.
/*since json_decode() decodes json, it MUST check if the argument passed in is json, so logically one can assume that json_decode() also functions as a json checker*/
//thus....
if(json_decode($input_json) == NULL)
{
echo("not valid json!");
}else
{
$my_json_object = json_decode($input_json);
}
Please note that this function does NOT convert back to PHP values all strings resulting from a call to json-encode.
Since the json spec says that "A JSON text is a serialized object or array", this function will return NULL when decoding any json string that does not represent either an object or an array.
To successfully encode + decode single php values such as strings, booleans, integers or floats, you will have to wrap them in an array before converting them.
There seems to be a difference in the way json_decode works between 5.2.9 and 5.2.6. Trying to run json_decode on a URL in 5.2.6 will return the URL, but in 5.2.9 it will return NULL.
5.2.6
var_dump(json_decode("http://www.php.net")); // Displays string(18) "http://www.php.net"
5.2.9
var_dump(json_decode("http://www.php.net")); // Displays NULL
The servers I tested it on both had json version 1.2.1.
