Skip to main content

Read, Decode, Encode, Write JSON in PHP

· 9 min read
Nico Dupont

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:

  1. Open and read the file's content with file_get_contents($path)
  2. Convert the JSON string to an associative array with json_decode($jsonString, true)
  3. 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:

  1. Convert the list of associative array to a JSON string with json_encode($jsonData, JSON_PRETTY_PRINT)
  2. Open the new JSON file with fopen($path, 'w')
  3. Write the JSON string with fwrite($fp, $jsonString)
  4. 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. 🐋