JSON (JavaScript Object Notation) is a standard file format for data exchange between applications.
In this tutorial, we will learn how to perform the most common manipulation, such as encoding, decoding, and converting JSON to Array and Array to JSON with the help of examples.
We'll also discover how to read and write JSON files in PHP. Finally, we'll look at how to stream a big JSON file while using very little memory.
The whole code and examples are available in a GitHub repository; it comes packaged as a simple Symfony project and provides a Docker image.
JSON String Example
In this tutorial, we'll use the following JSON string containing a list of movies and their properties.
[
{
"id": "287947",
"title": "Shazam!",
"poster": "https://image.tmdb.org/t/p/w500/xnopI5Xtky18MPhK40cZAGAOVeV.jpg",
"overview": "A boy is given the ability to become an adult superhero in times of need with a single magic word.",
"release_date": "1553299200",
"genres": [
"Action",
"Comedy",
"Fantasy"
]
},
{
"id": "299537",
"title": "Captain Marvel",
"poster": "https://image.tmdb.org/t/p/w500/AtsgWhDnHTq68L0lLsUrCnM7TjG.jpg",
"overview": "The story follows Carol Danvers as she becomes one of the universe\u2019s most powerful heroes when Earth is caught in the middle of a galactic war between two alien races. Set in the 1990s, Captain Marvel is an all-new adventure from a previously unseen period in the history of the Marvel Cinematic Universe.",
"release_date": "1551830400",
"genres": [
"Action",
"Adventure",
"Science Fiction"
]
}
]
Convert a JSON String to an Associative Array Using json_decode
We use json_decode
to convert (decode) the string to a PHP associative array.
The second parameter of json_decode
specifies if we want to get each JSON object as an associative array or as an object. Here, we go for the associative array option.
$jsonString = '[{"id":"287947","title":"Shazam!","poster":"https:\/\/image.tmdb.org\/t\/p\/w500\/xnopI5Xtky18MPhK40cZAGAOVeV.jpg","overview":"A boy is given the ability to become an adult superhero in times of need with a single magic word.","release_date":"1553299200","genres":["Action","Comedy","Fantasy"]},{"id":"299537","title":"Captain Marvel","poster":"https:\/\/image.tmdb.org\/t\/p\/w500\/AtsgWhDnHTq68L0lLsUrCnM7TjG.jpg","overview":"The story follows Carol Danvers as she becomes one of the universe\u2019s most powerful heroes when Earth is caught in the middle of a galactic war between two alien races. Set in the 1990s, Captain Marvel is an all-new adventure from a previously unseen period in the history of the Marvel Cinematic Universe.","release_date":"1551830400","genres":["Action","Adventure","Science Fiction"]}]';
$jsonArray = json_decode($jsonString, true); // true for associative arrays, false for objects
var_dump($jsonArray);
The result is an array containing one associative array for each movie. The keys of each associative array are the fields of the JSON object.
array(2) {
[0]=>
array(6) {
["id"]=>
string(6) "287947"
["title"]=>
string(7) "Shazam!"
["poster"]=>
string(63) "https://image.tmdb.org/t/p/w500/xnopI5Xtky18MPhK40cZAGAOVeV.jpg"
["overview"]=>
string(98) "A boy is given the ability to become an adult superhero in times of need with a single magic word."
["release_date"]=>
string(10) "1553299200"
["genres"]=>
array(3) {
[0]=>
string(6) "Action"
[1]=>
string(6) "Comedy"
[2]=>
string(7) "Fantasy"
}
}
[1]=> // ... the second movie
}
Convert an Associative Array to a JSON string Using json_encode
We use json_encode
to convert (encode) the associative array to a JSON string.
The second parameter of json_encode
specifies the format of the string. We can go for the compact option by default. We can also use the pretty format; it includes line breaks and spaces to make the result more human-readable.
$jsonArray = [
[
"id" => "287947",
"title" => "Shazam!",
"poster" => "https://image.tmdb.org/t/p/w500/xnopI5Xtky18MPhK40cZAGAOVeV.jpg",
"overview" => "A boy is given the ability to become an adult superhero in times of need with a single magic word.",
"release_date" => "1553299200",
"genres"=> ["Action", "Comedy", "Fantasy"]
],
[
"id" => "299537",
"title" => "Captain Marvel",
"poster" => "https://image.tmdb.org/t/p/w500/AtsgWhDnHTq68L0lLsUrCnM7TjG.jpg",
"overview" => "The story follows Carol Danvers as she becomes one of the universe’s most powerful heroes when Earth is caught in the middle of a galactic war between two alien races. Set in the 1990s, Captain Marvel is an all-new adventure from a previously unseen period in the history of the Marvel Cinematic Universe.",
"release_date" => "1551830400",
"genres"=> ["Action", "Adventure", "Science Fiction"]
]
];
// compact format
$compactJsonString = json_encode($jsonArray);
echo $compactJsonString.PHP_EOL;
// pretty human-readable format
$prettyJsonString = json_encode($jsonArray, JSON_PRETTY_PRINT);
echo $prettyJsonString.PHP_EOL;
The compact JSON string format:
[{"id":"287947","title":"Shazam!","poster":"https:\/\/image.tmdb.org\/t\/p\/w500\/xnopI5Xtky18MPhK40cZAGAOVeV.jpg","overview":"A boy is given the ability to become an adult superhero in times of need with a single magic word.","release_date":"1553299200","genres":["Action","Comedy","Fantasy"]},{"id":"299537","title":"Captain Marvel","poster":"https:\/\/image.tmdb.org\/t\/p\/w500\/AtsgWhDnHTq68L0lLsUrCnM7TjG.jpg","overview":"The story follows Carol Danvers as she becomes one of the universe\u2019s most powerful heroes when Earth is caught in the middle of a galactic war between two alien races. Set in the 1990s, Captain Marvel is an all-new adventure from a previously unseen period in the history of the Marvel Cinematic Universe.","release_date":"1551830400","genres":["Action","Adventure","Science Fiction"]}]
The pretty JSON string format:
[
{
"id": "287947",
"title": "Shazam!",
"poster": "https:\/\/image.tmdb.org\/t\/p\/w500\/xnopI5Xtky18MPhK40cZAGAOVeV.jpg",
"overview": "A boy is given the ability to become an adult superhero in times of need with a single magic word.",
"release_date": "1553299200",
"genres": [
"Action",
"Comedy",
"Fantasy"
]
},
{
"id": "299537",
"title": "Captain Marvel",
"poster": "https:\/\/image.tmdb.org\/t\/p\/w500\/AtsgWhDnHTq68L0lLsUrCnM7TjG.jpg",
"overview": "The story follows Carol Danvers as she becomes one of the universe\u2019s most powerful heroes when Earth is caught in the middle of a galactic war between two alien races. Set in the 1990s, Captain Marvel is an all-new adventure from a previously unseen period in the history of the Marvel Cinematic Universe.",
"release_date": "1551830400",
"genres": [
"Action",
"Adventure",
"Science Fiction"
]
}
]
Read a JSON File in PHP
We'll use the same format here; the file movies-10.json
contains a list of 10 movies:
[
{
"id": "287947",
"title": "Shazam!",
"poster": "https://image.tmdb.org/t/p/w500/xnopI5Xtky18MPhK40cZAGAOVeV.jpg",
"overview": "A boy is given the ability to become an adult superhero in times of need with a single magic word.",
"release_date": "1553299200",
"genres": [
"Action",
"Comedy",
"Fantasy"
]
},
{
"id": "299537",
"title": "Captain Marvel",
"poster": "https://image.tmdb.org/t/p/w500/AtsgWhDnHTq68L0lLsUrCnM7TjG.jpg",
"overview": "The story follows Carol Danvers as she becomes one of the universe\u2019s most powerful heroes when Earth is caught in the middle of a galactic war between two alien races. Set in the 1990s, Captain Marvel is an all-new adventure from a previously unseen period in the history of the Marvel Cinematic Universe.",
"release_date": "1551830400",
"genres": [
"Action",
"Adventure",
"Science Fiction"
]
},
// ... and more lines
]
We parse the JSON file using native PHP functions:
- Open and read the file's content with
file_get_contents($path)
- Convert the JSON string to an associative array with
json_decode($jsonString, true)
- Print the associative array with
var_dump($jsonData)
$path = 'data/movies-10.json';
$jsonString = file_get_contents($path);
$jsonData = json_decode($jsonString, true);
var_dump($jsonData);
The result:
array(10) {
[0]=>
array(6) {
["id"]=>
string(6) "287947"
["title"]=>
string(7) "Shazam!"
["poster"]=>
string(63) "https://image.tmdb.org/t/p/w500/xnopI5Xtky18MPhK40cZAGAOVeV.jpg"
["overview"]=>
string(98) "A boy is given the ability to become an adult superhero in times of need with a single magic word."
["release_date"]=>
string(10) "1553299200"
["genres"]=>
array(3) {
[0]=>
string(6) "Action"
[1]=>
string(6) "Comedy"
[2]=>
string(7) "Fantasy"
}
}
// ... and more lines
}
Write a JSON File in PHP
We create and write a JSON file from an associative array:
- Convert the list of associative array to a JSON string with
json_encode($jsonData, JSON_PRETTY_PRINT)
- Open the new JSON file with
fopen($path, 'w')
- Write the JSON string with
fwrite($fp, $jsonString)
- Close the file with
fclose($fp)
$path = 'data/new-file.json';
// JSON data as an array
$jsonData = [
[
"id" => "287947",
"title" => "Shazam!",
"poster" => "https://image.tmdb.org/t/p/w500/xnopI5Xtky18MPhK40cZAGAOVeV.jpg",
"overview" => "A boy is given the ability to become an adult superhero in times of need with a single magic word.",
"release_date" => "1553299200",
"genres"=> ["Action", "Comedy", "Fantasy"]
],
[
"id" => "299537",
"title" => "Captain Marvel",
"poster" => "https://image.tmdb.org/t/p/w500/AtsgWhDnHTq68L0lLsUrCnM7TjG.jpg",
"overview" => "The story follows Carol Danvers as she becomes one of the universe’s most powerful heroes when Earth is caught in the middle of a galactic war between two alien races. Set in the 1990s, Captain Marvel is an all-new adventure from a previously unseen period in the history of the Marvel Cinematic Universe.",
"release_date" => "1551830400",
"genres"=> ["Action", "Adventure", "Science Fiction"]
]
];
// Convert JSON data from an array to a string
$jsonString = json_encode($jsonData, JSON_PRETTY_PRINT);
// Write in the file
$fp = fopen($path, 'w');
fwrite($fp, $jsonString);
fclose($fp);
CSV for Comma-Separated Values is another standard format to exchange data between applications, and it's pretty straightforward to convert from JSON to CSV (and from CSV to JSON).
Out of Memory!
When reading a large JSON file, you'll quickly encounter a memory consumption issue: "Error: Allowed memory size of X bytes exhausted".
It's normal! The native methods load the entire content in memory. You can raise the memory_limit
until reaching the limits of memory of your server. Some files are so large that it will not be enough.
Great news, there is an alternative approach; let's explore it.
Stream a Big JSON File
We use a JSON file including 500k movies records; it weights almost 300MB:
-rw-rw-rw- 1 nico nico 284M mars 12 13:20 movies-500000.json
We'll install and use the halaxa/json-machine
library.
composer require halaxa/json-machine
JSON Machine is an efficient PHP JSON stream parser based on generators.
Read our big JSON file:
// I'm using here the Symfony Console & StopWatch components
$section = 'read_json_file';
$this->stopwatch->start($section);
$path = 'data/movies-500000.json';
// open the JSON file
$jsonData = Items::fromFile($path, ['decoder' => new ExtJsonDecoder(true)]);
// iterate over each document
foreach ($jsonData as $object) {
// do nothing, but we want to browse each object
// echo $object["title"];
}
$this->stopwatch->stop($section);
$output->writeln("I read ".iterator_count($jsonData)." rows from the JSON File ".$path);
$output->writeln((string) $this->stopwatch->getEvent($section));
And here is the result:
I read 500000 rows from the JSON File data/movies-500000.json
default/read_json_file: 8.00 MiB - 17976 ms
Yes, we parsed our 500k JSON records in 20 seconds and using only 8MB!
We can't predict how big the file to integrate will be in some cases. Using a streaming approach will make your code more robust, fast, memory-efficient, and future-proof.
Download the Code and Examples
You can find all the code and examples in this GitHub repository.
It's packaged as a simple Symfony project, a set of commands, it also comes with a Docker image. 🐋