JSON With PHP – A Complete Guide
So, you’ll have read the article: Understanding JSON and have a big picture what JSON is, well, in this article, we will dig more deep about json: “JSON in PHP” including some real-world example.
PHP support JSON since PHP 5.2 by introducing json_encode
and json_decode
function and continue to support it by fixed bugs and add more features.
Environment
Before going any further, you need to know that when writing this article, I’m using PHP version 5.6 running on Windows 10 operating system.
So, if you use a different version of PHP especially for the previous version, then you may get a different result as there are some bugs there.
I recommend using PHP >= 5.4 as these versions more mature in handling JSON.
I. Creating JSON With PHP
To create JSON with PHP as well as other programming languages, not recommended to create it manually, why? because risky, always use built-in function, in this case json_encode()
instead.
Why should use built-in function?
Because every built-in function, including json_encode()
will take into account existing standards, so the resulting JSON can be assured valid and meet the existing standards (ECMA-404)
An example of json_encode()
function:
$config = array(
'site_title' =>'Webdevzoom'
,'site_url'=>'http://webdevzoom.com'
,'themes'=>'crystal'
);
echo json_encode($config);
// Result
{"site_title":"Webdevzoom","site_url":"http:\/\/webdevzoom.com","themes":"crystal"}
I.1. Writing Term
json_encode()
function has the following form:
json_encode ($ value [, int $ options = 0 [, int $depth = 512]])
Arguments:
- The
$value
argument can be passed with all data types including objects and arrays excluding resources. The most used data type is array. In addition, The$value
argument must be encoded using UTF-8, this often caused an error when creating JSON from database data. - The
$options
argument used to change the default parameters (we’ll discuss it later), it can be passed using predefined constants. $depth
is the number of depth (child) of the$value
.
Because the most used data type is array, so… for simplicity, we’ll only use this data type for the entire article.
I.2 json_encode()
Basic Usage
We can use json_encode()
function for indexed arrays, as well as associative arrays, or a combination of both, for example, we have a table in a database named config that contains the following data:
id | option | value |
---|---|---|
1 | site_title | Webdevzoom |
2 | site_description | Web developer community for euthiast programmer |
3 | site_url | http://webdevzoom.com |
4 | path | user\htdocs\wdz |
5 | themes | wdz |
Example #1: Indexed Array
$conn = mysqli_connect('localhost', 'root', '', 'test');
$query = mysqli_query($conn, 'SELECT * FROM config');
while ($row = mysqli_fetch_assoc($query)) {
$json[] = $row['value'];
}
echo '<pre>'; print_r($json); echo '</pre>';
$json = json_encode($json);
echo $json;
The result:
// ARRAY
Array
(
[0] => Webdevzoom
[1] => Web developer community for euthiast programmer
[2] => http://webdevzoom.com
[3] => user\htdocs\wdz
[4] => wdz
)
// JSON with array data type
["Webdevzoom","Web developer community for euthiast programmer","http:\/\/webdevzoom.com","user\\htdocs\\wdz","wdz"]
Example #2: Associative Array
$conn = mysqli_connect('localhost', 'root', '', 'test');
$query = mysqli_query($conn, 'SELECT * FROM config');
while ($row = mysqli_fetch_assoc($query)) {
$json['site_option'][ $row['option'] ] = $row['value'];
}
$json['site_db'] = array(
'host' => 'localhost'
, 'user' => 'root'
, 'pass' => 'defult'
);
echo '<pre>'; print_r($json); echo '</pre>';
$json = json_encode($json);
echo $json;
The result:
Array
(
[site_option] => Array
(
[site_title] => Webdevzoom
[site_description] => Web developer community for euthiast programmer
[site_url] => http://webdevzoom.com
[base_path] => user\htdocs\wdz
[themes] => wdz
)
[site_db] => Array
(
[host] => localhost
[user] => root
[pass] => defult
)
)
JSON with object data type
{"site_option":{"site_title":"Webdevzoom","site_description":"Web developer community for euthiast programmer","site_url":"http:\/\/webdevzoom.com","base_path":"user\\htdocs\\wdz","themes":"wdz"},"site_db":{"host":"localhost","user":"root","pass":"defult"}}
JSON object VS JSON array
From the above examples, we got two kinds of JSON data type: array and object. In PHP we don’t need to worry about that JSON data type as when we decode it PHP will convert all of them into PHP array (JSON object to an associative array and JSON array into an indexed array) or PHP Object, so just focus on json_encode()
function.
Learn more about JSON object and array data type: Understanding JSON – A Comprehensive Guide
Error while creating JSON data from a database
JSON is often used to display data from a database, like the examples above.
Data in a database might come from many places and may not be encoded using UTF-8, so when converting to JSON using json_encode()
may resulting an error:
Malformed UTF-8 characters, possibly incorrectly encoded
To solve that, you can read the article: JSON Error In PHP – Creating JSON From Database
The importance of escaping slash character (\/)
By default, Starting from PHP 5.4.0, the json_encode()
function will automatically escape any slash character, e.g. from / to\/
With such behavior, for url, will look bit mess, eg: http://webdevzoom.com/images/json_logo.png become http:\/\/webdevzoom.com\/images\/json_logo.png
In JSON standard, escaping slash is optional, not mandatory, if we don’t want it, we can add JSON_UNESCAPE_SLASH
in options argument.
So, what are the benefits of escaping slash?
The main purpose is to prevent script execution.
If a JSON string contains a closing tag </script>
, and then placed within <script>
tag, it will cause the main script stopped and javascript code within the JSON string will be executed, for example:
<script type = "text/javascript">
var json = {"content": "</script><script>alert(document.cookie)</script>"}
</script>
In the above example, the javascript code in the JSON string will be executed, this is dangerous and potentially arise XSS attacks.
So… we should let the slash character escaped, or we can escape it if we really sure that the content of the JSON string is safe.
I.3 json_encode()
Second Argument
The json_encode()
function provides an optional second argument that can be used to change default parameters, actually, the value of this option are bitmasks: 1, 2, 4, 8, 16, etc., but to make it easier, PHP has provided constants representing that values, such as:
JSON_HEX_TAG
to convert HTML tags (<) and (>) to \ u003C and \ u003EJSON_HEX_APOS
to convert the single quote (‘) to \ u0027. This is helpful when putting JSON into the HTML element attribute.JSON_HEX_QUOT
to convert double quote (“) to \ u0022JSON_HEX_AMP
to convert (&) to \ u0026JSON_PRETTY_PRINT
to format JSON output by adding space characters (not tabs). It makes the JSON string more readable. This option exists on PHP >= 5.4.0. An example:$array = array('site_title' => 'Webdevzoom', 'site_url' => 'http://webdevzoom.com'); echo json_encode($array); // Result: {"site_title":"Webdevzoom","site_url":"http:\/\/webdevzoom.com"} echo json_encode($array, JSON_PRETTY_PRINT); // Result: { "site_title": "Webdevzoom", "site_url": "http:\/\/webdevzoom.com" }
JSON_UNESCAPED_SLASHES
to not escape the slash character (/), for example:$array = array('site_title' => 'Webdevzoom', 'site_url' =>'http://webdevzoom.com/blog/'); echo json_encode($array); // Result: {"site_title":"Webdevzoom","site_url":"http:\/\/webdevzoom.com\/blog\/"} echo json_encode($array, JSON_UNESCAPED_SLASHES); // Hasil: {"site_title":"Webdevzoom","site_url":"http://webdevzoom.com/blog/"}
JSON_FORCE_OBJECT
. Force the resulting JSON string to object instead of array. This is useful if the recipient requires that the JSON string should be an object. Example:$array = array('Webdevzoom', 'http://webdevzoom.com/blog/'); echo json_encode($array); // Result an array: ["Webdevzoom","http:\/\/webdevzoom.com\/blog\/"] echo json_encode($array, JSON_FORCE_OBJECT); // Result an object: {"0":"Webdevzoom","1":"http:\/\/webdevzoom.com\/blog\/"}
The above constants are the most used, if you want to know all list of constants, you can visit the official page: PHP: Predefined Constant.
To use more than one option, use bitwise OR (|), for example:
$json = array('html' => '<div class="title">Example</div>');
$encode = json_encode($json, JSON_HEX_TAG | JSON_HEX_QUOT);
II. Parsing JSON With PHP
So we have known how to create JSON with PHP, now, we discuss how to convert the JSON string back to data that will make us easy to work with.
In PHP, JSON string can be converted into two forms: array and object. To convert JSON string to both array and object we use json_decode()
function. This function has the following form:
json_decode( string $json [, bool $assoc = FALSE [, int $depth = 512 [, int $options = 0 ]]] )
The $json
argument is mandatory, while others are optional. If the second argument $assoc
is set to true
, then the output is a PHP array, otherwise PHP object, for example, we have the JSON string as follows:
$json = '{"site_option":
{"site_title":"Webdevzoom"
,"site_description":"Web developer community for euthiast programmers"
,"site_url":"http://webdevzoom.com"
,"themes":"wdz"
}
,"site_db":
{"host":"localhost"
,"user":"root"
,"pass":"defult"
}
}';
Example #1: Result an object:
$decode = json_decode($json);
var_dump($decode);
/* Result:
object(stdClass)#1 (2) {
["site_option"]=>
object(stdClass)#2 (4) {
["site_title"]=>
string(10) "Webdevzoom"
["site_description"]=>
string(48) "Web developer community for euthiast programmers"
["site_url"]=>
string(21) "http://webdevzoom.com"
["themes"]=>
string(3) "wdz"
}
["site_db"]=>
object(stdClass)#3 (3) {
["host"]=>
string(9) "localhost"
["user"]=>
string(4) "root"
["pass"]=>
string(6) "defult"
}
}
*/
Example #2: Result an array:
$decode = json_decode($json, true);
echo '<pre>'; print_r($decode); echo '</pre>';
/*Result:
Array
(
[site_option] => Array
(
[site_title] => Webdevzoom
[site_description] => Web developer community for euthiast programmers
[site_url] => http://webdevzoom.com
[themes] => wdz
)
[site_db] => Array
(
[host] => localhost
[user] => root
[pass] => defult
)
)
*/
Prefer Object or Array? it depends on the situation, generally, people use arrays, but if they are in Object Oriented Environment, object is more convenience.
NOTE:
JSON string can come from many sources: e.g from databases, files (.txt, .json, etc.), or from external URLs, in order to make this post not too weight, this topic discussed in another article.
III. Handling Error On JSON
When using json_encode()
and json_encode()
functions and an error occurred, then both functions do not generate any error messages, json_encode()
results an empty value, while for json_decode()
results a NULL
value
Well, to know that an error occurs, we can use one of the following two functions:
json_last_error()
This function available since PHP 5.3.0, it will generate an integer value (that has a certain meaning) as a result of the executionjson_encode()
andjson_decode()
functions.json_last_error_msg()
This function available in since PHP 5.5.0, the function will directly generate a string that reflects the execution of thejson_encode()
andjson_decode()
functions.
The easiest way to find out the error is to use the json_last_error_msg()
function as it directly tell us what just happened, for example:
$json = '{"site_option":
{"site_title":"Webdevzoom"
,"site_url":"http://webdevzoom.com"
}
}';
$decode = json_decode($json, true);
$last_error = json_last_error_msg();
if (strtolower($last_error) != 'no error') {
echo 'ERROR: ' . $last_error; die;
}
NOTE: In the above example, if no error occurs, the json_last_error_msg()
will result the string “No error” so we evaluate it using if(strtolower($ last_error) != 'no error'))
To be more flexible and more organized in handling error messages, we can use the function json_last_error()
This function will generate an integer ranging from 0 s.d 10
This integer value has been translated to constants as follows:
Constant | Integer | Mean | PHP Version |
---|---|---|---|
JSON_ERROR_NONE |
0 | No error has occurred | |
JSON_ERROR_DEPTH |
1 | The maximum stack depth has been exceeded | |
JSON_ERROR_STATE_MISMATCH |
2 | Invalid or malformed JSON | |
JSON_ERROR_CTRL_CHAR |
3 | Control character error, possibly incorrectly encoded | |
JSON_ERROR_SYNTAX |
4 | Syntax error | |
JSON_ERROR_UTF8 |
5 | Malformed UTF-8 characters, possibly incorrectly encoded | PHP 5.3.3 |
JSON_ERROR_RECURSION |
6 | One or more recursive references in the value to be encoded | PHP 5.5.0 |
JSON_ERROR_INF_OR_NAN |
7 | One or more NAN or INF values in the value to be encoded |
PHP 5.5.0 |
JSON_ERROR_UNSUPPORTED_TYPE |
8 | A value of a type that cannot be encoded was given | PHP 5.5.0 |
JSON_ERROR_INVALID_PROPERTY_NAME |
9 | A property name that cannot be encoded was given | PHP 7.0.0 |
JSON_ERROR_UTF16 |
10 | Malformed UTF-16 characters, possibly incorrectly encoded | PHP 7.0.0 |
So… if we echo that constant we’ll get the integer value, e.g echo JSON_ERROR_SYNTAX
then we’ll get 4
Using that kind of error handling, make us possible to customize the error message. This is useful for example for localization, we can translate the error message to different languages.
Example of using constant:
$json = '{"title":"Understansing JSON - Part II}';
$decode = json_decode($json);
if (json_last_error() == JSON_ERROR_UTF8) {
echo 'ERROR: Your data contains non UTF-8 encoded character';
}
Using integer:
if (json_last_error() == 5) {
echo 'ERROR: Your data contains non UTF-8 encoded character';
}
To handle all error messages, we can create an array that contains all possible error:
$json_error = array {
JSON_ERROR_DEPTH => 'Maximum stach depth exceed, try to increase the depth limit'
, JSON_ERROR_STATE_MISMATCH => 'Invalid JSON form'
, JSON_ERROR_CTRL_CHAR => 'Control character error, make sure your string use UTF-8 encoding'
, JSON_ERROR_SYNTAX => 'Syntax error'
, JSON_ERROR_UTF8 => 'Invalid character, make sure your string use UTF-8 encoding'
, JSON_ERROR_RECURSION => 'One or more recursive references in the value to be encoded'
, JSON_ERROR_INF_OR_NAN => 'Your string contains INF or NAN value'
, JSON_ERROR_UNSUPPORTED_TYPE => 'A value of a type that cannot be encoded'
, JSON_ERROR_INVALID_PROPERTY_NAME => 'A property name of JSON that cannot be encoded'
, JSON_ERROR_UTF16 => 'Invalid UTF-16 characters, make sure you string corectly encoded'
}
$json = '{"title":"Understanding JSON in PHP - Part II}';
$decode = json_decode($json, true);
$last_error = json_last_error();
if ($last_error == 0) {
print_r($decode);
} else {
echo $json_error[$last_error];
}
IV. JSON and XSS
Any string associated with javascript and HTML will have a risk of XSS attack, as well as JSON string.
An XSS attack happens when the HTML code contains <script>
tag that comes from an untrusted source (such as an input form of a website, where visitors may inject any malicious script).
That script tag contains a javascript code that will expose any sensitive data and send them to some place that have been specified by the script maker.
Related to JSON, creating JSON with json_encode()
function is secure, because (as previously mentioned) the function has escaped slash (<\/script>
) – starting from PHP version 5.4.0 -, so javascript code inside JSON will not be executed.
Moreover, the protection of XSS attack should be done before we use that data, e.q., filtering input form before inserting into the database, filtering query string from URL before using it, etc…
So when we want to use that data, e.q creating a JSON string or other purposes, they are already sanitized and safe.
Do we need HEX option?
Discussion that often arises is if our JSON contains HTML tags, or <script>
tags, should we use the option JSON_HEX_XXX
to convert HTML element into hex value? such as the following?
$array = array('html' => '</script><script>document.cookie</script>');
$json = json_encode($json, JSON_HEX_TAG | JSON_HEX_QUOT | JSON_HEX_APOS | JSON_HEX_AMP);
Again, the json_encode()
function is secure so that the use of JSON_HEX_xxx
argument is no longer necessary.
Moreover, we don’t need that if we trust the data source, e.g. from our own server and we created that data, or we really sure that the data already sanitized well.
V. Wrap Up
PHP provides complete built-in tools to work with JSON, things to note is the version of PHP, because in PHP < 5.6, there are some bugs that are sometimes troublesome.
Happy encoding !!!.
Subscibe Now
Loves articles on webdevzoom.com? join our newsletter to get quality article right to your inbox. Nothing else, just quality stuff!!!