PHP JSON tutorial shows how to work with JSON in PHP. JSON is a lightweight data-interchange format.
last modified February 16, 2025
PHP JSON tutorial shows how to work with JSON in PHP.
JSON (JavaScript Object Notation) is a lightweight data-interchange format. It is easily read and written by humans and parsed and generated by machines. The application/json is the official Internet media type for JSON. The JSON filename extension is .json.
The json_encode function returns the JSON representation of the given value. The json_decode takes a JSON encoded string and converts it into a PHP variable.
PHP frameworks such as Symfony and Laravel have built-in methods that work with JSON.
In the following example, we use the json_encode function.
encode.php
<?php
$data = [“falcon”, “sky”, “cloud”, “orange”, “wood”, “forest”];
header(‘Content-type:application/json;charset=utf-8’); echo json_encode($data);
The example transforms a PHP array into a JSON string.
$ php -S localhost:8000 encode.php
We start the server and locate to the localhost:8000.
Figure: JSON view in Firefox
Modern web browsers show JSON view for JSON data when they receive an appropriate content type in the header of the response.
In the following example, we use the json_decode function.
decode.php
<?php
$data = ‘{ “name”: “John Doe”, “occupation”: “gardener” }’;
$a = json_decode($data, true);
header(‘Content-type:text/html;charset=utf-8’); echo “{$a[“name”]} is a {$a[“occupation”]}”;
The example transforms a JSON string into a PHP variable.
$ php -S localhost:8000 decode.php
We start the server.
$ curl localhost:8000 John Doe is a gardener
We send a GET request with curl.
In the following example, we read JSON data from a file.
data.json
[ {“name”: “John Doe”, “occupation”: “gardener”, “country”: “USA”}, {“name”: “Richard Roe”, “occupation”: “driver”, “country”: “UK”}, {“name”: “Sibel Schumacher”, “occupation”: “architect”, “country”: “Germany”}, {“name”: “Manuella Navarro”, “occupation”: “teacher”, “country”: “Spain”}, {“name”: “Thomas Dawn”, “occupation”: “teacher”, “country”: “New Zealand”}, {“name”: “Morris Holmes”, “occupation”: “programmer”, “country”: “Ireland”} ]
This is the JSON data.
readjson.php
<?php
$filename = ‘data.json’;
$data = file_get_contents($filename); $users = json_decode($data); ?>
<html> <table> <tbody> <tr> <th>Name</th> <th>Occupation</th> <th>Country</th> </tr> <?php foreach ($users as $user) { ?> <tr> <td> <?= $user->name; ?> </td> <td> <?= $user->occupation; ?> </td> <td> <?= $user->country; ?> </td> </tr> <?php } ?> </tbody> </table> </html>
In the code example, we read the file with file_get_contents and decode it into an PHP array with json_decode. Later, we place the data into a table utilizing PHP foreach loop.
In the following example, we read data from an SQLite database and return it in JSON.
cities.sql
BEGIN TRANSACTION; DROP TABLE IF EXISTS cities;
CREATE TABLE cities(id INTEGER PRIMARY KEY, name TEXT, population INTEGER); INSERT INTO cities(name, population) VALUES(‘Bratislava’, 432000); INSERT INTO cities(name, population) VALUES(‘Budapest’, 1759000); INSERT INTO cities(name, population) VALUES(‘Prague’, 1280000); INSERT INTO cities(name, population) VALUES(‘Warsaw’, 1748000); INSERT INTO cities(name, population) VALUES(‘Los Angeles’, 3971000); INSERT INTO cities(name, population) VALUES(‘New York’, 8550000); INSERT INTO cities(name, population) VALUES(‘Edinburgh’, 464000); INSERT INTO cities(name, population) VALUES(‘Berlin’, 3671000); COMMIT;
This SQL code creates a cities table in SQLite.
$ sqlite3 test.db sqlite> .read cities.sql sqlite> SELECT * FROM cities; 1|Bratislava|432000 2|Budapest|1759000 3|Prague|1280000 4|Warsaw|1748000 5|Los Angeles|3971000 6|New York|8550000 7|Edinburgh|464000 8|Berlin|3671000
With the sqlite3 command line tool, we generate an SQLite database and create the cities table.
fetch_all.php
<?php
$db = new SQLite3(’test.db’); $res = $db->query(‘SELECT * FROM cities’); $cities = [];
while ($row = $res->fetchArray()) { $cities[] = $row; }
header(‘Content-type:application/json;charset=utf-8’); echo json_encode([‘cities’ => $cities]);
In the example, we retrieve the data from the database and return it as JSON.
In the following example, we use JavaScript fetch API to get the JSON data from a PHP script.
data.json
[ {“name”: “John Doe”, “occupation”: “gardener”, “country”: “USA”}, {“name”: “Richard Roe”, “occupation”: “driver”, “country”: “UK”}, {“name”: “Sibel Schumacher”, “occupation”: “architect”, “country”: “Germany”}, {“name”: “Manuella Navarro”, “occupation”: “teacher”, “country”: “Spain”}, {“name”: “Thomas Dawn”, “occupation”: “teacher”, “country”: “New Zealand”}, {“name”: “Morris Holmes”, “occupation”: “programmer”, “country”: “Ireland”} ]
The JSON data is stored in a file.
data.php
<?php
$filename = ‘data.json’;
$data = file_get_contents($filename); header(‘Content-type:application/json;charset=utf-8’); echo $data;
We read the data and return it to the client.
index.html
<!DOCTYPE html> <html lang=“en”>
<head> <meta charset=“UTF-8”> <meta name=“viewport” content=“width=device-width, initial-scale=1.0”> <title>Home page</title> <style> th, td { font: 15px ‘Segoe UI’; }
table,
th,
td {
border: solid 1px #ddd;
border-collapse: collapse;
padding: 2px 3px;
text-align: center;
}
tr:nth-child(odd) {background: #efefef}
th {
font-weight: bold;
}
</style>
</head>
<body>
<button id="getData">Get data</button>
<br>
<br>
<div id="output"></div>
<script>
const getBtn = document.getElementById('getData');
const output = document.getElementById('output');
const table = document.getElementById('table');
getBtn.addEventListener('click', () => {
fetch('/data.php')
.then((res) => {
return res.json();
})
.then((data) => {
output.innerHTML = '';
let table = createTableAndHeader();
output.appendChild(table);
appendRows(table, data);
})
.catch((err) => {
console.log("error fetching data");
console.log(err);
})
});
function createTableAndHeader() {
let table = document.createElement("table");
let tr = table.insertRow(-1);
let headers = ["Name", "Occupation", "Country"];
for (let i = 0; i < 3; i++) {
let th = document.createElement("th");
th.innerHTML = headers[i];
tr.appendChild(th);
}
return table;
}
function appendRows(table, data) {
for (let i = 0; i < data.length; i++) {
let tr = table.insertRow(-1);
for (const [_, value] of Object.entries(data[i])) {
let cell = tr.insertCell(-1);
cell.innerHTML = value;
}
}
}
</script>
</body>
</html>
We have a button in the document. When we click on the button, the fetch function retrieves JSON data from the data.php script. An HTML table is dynamically built and filled with the data.
Figure: HTML table filled with JSON data from fetch API
In the following example, we return JSON data from a Slim application.
$ composer req slim/slim $ composer req slim/psr7 $ composer req slim/http
We install slim/slim, slim/psr7, and slim/http packages.
public/index.php
<?php
use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; use Slim\Factory\AppFactory;
require DIR . ‘/../vendor/autoload.php’;
$app = AppFactory::create();
$app->get(’/city’, function (Request $request, Response $response): Response {
$cities = [
["id" => 1, "name" => "Bratislava", "population" => 432000],
["id" => 2, "name" => "Budapest", "population" => 1759000],
["id" => 3, "name" => "Prague", "population" => 1280000],
["id" => 4, "name" => "Warsaw", "population" => 1748000],
["id" => 5, "name" => "Los Angeles", "population" => 3971000],
["id" => 6, "name" => "New York", "population" => 8550000],
["id" => 7, "name" => "Edinburgh", "population" => 464000],
["id" => 8, "name" => "Berlin", "population" => 3671000],
];
return $response->withJson(["cities" => $cities]);
});
$app->run();
We use the withJson method of the Response to return JSON data.
In the following example, we send a JSON response from a Symfony application.
$ symfony new symjson $ cd symjson
A new application is created.
$ composer req annot $ composer req symfony/orm-pack $ composer req symfony/console
We install the annot, symfony/orm-pack, and symfony/console components.
.env
… DATABASE_URL=sqlite:///%kernel.project_dir%/var/ydb.db …
We set up a database URL for the SQLite database.
$ php bin/console doctrine:database:create
We create the database.
src/Command/CreateCityTable.php
<?php
namespace App\Command;
use Doctrine\DBAL\Driver\Connection; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface;
class CreateCityTable extends Command { private $conn;
public function __construct(Connection $conn)
{
$this->conn = $conn;
parent::__construct();
}
protected function configure()
{
$this->setName('app:create-table')
->setDescription('Creates City table')
->setHelp('This command creates a City table');
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$q1 = "CREATE TABLE cities(id INTEGER PRIMARY KEY, name TEXT, population INTEGER)";
$this->conn->executeQuery($q1);
$q2 = "INSERT INTO cities(name, population) VALUES('Bratislava', 432000)";
$this->conn->executeQuery($q2);
$q3 = "INSERT INTO cities(name, population) VALUES('Budapest', 1759000)";
$this->conn->executeQuery($q3);
$q4 = "INSERT INTO cities(name, population) VALUES('Prague', 1280000)";
$this->conn->executeQuery($q4);
$q5 = "INSERT INTO cities(name, population) VALUES('Warsaw', 1748000)";
$this->conn->executeQuery($q5);
$q6 = "INSERT INTO cities(name, population) VALUES('Los Angeles', 3971000)";
$this->conn->executeQuery($q6);
$q7 = "INSERT INTO cities(name, population) VALUES('New York', 8550000)";
$this->conn->executeQuery($q7);
$q8 = "INSERT INTO cities(name, population) VALUES('Edinburgh', 464000)";
$this->conn->executeQuery($q8);
$q9 = "INSERT INTO cities(name, population) VALUES('Berlin', 3671000)";
$this->conn->executeQuery($q9);
$output->writeln('table successfully created');
return Command::SUCCESS;
}
}
This is a command that creates the cities table in the database.
$ php bin/console app:create-table
The command is executed.
src/Repository/CityRepository.php
<?php
namespace App\Repository;
use Doctrine\DBAL\Driver\Connection;
class CityRepository { protected $conn;
public function __construct(Connection $conn)
{
$this->conn = $conn;
}
public function all(): array
{
$queryBuilder = $this->conn->createQueryBuilder();
$queryBuilder->select('*')->from('cities');
$stm = $queryBuilder->execute();
return $stm->fetchAll();
}
}
In the CityRepository, we have the all method which retrieves all rows. We use the Doctrine DBAL to execute the database query.
src/Controller/CityController.php
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\Routing\Annotation\Route; use App\Repository\CityRepository;
class CityController extends AbstractController { /** * @Route("/city", name=“city”) * @param CityRepository $cityRepository * @return JsonResponse */ public function index(CityRepository $cityRepository): JsonResponse { $cities = $cityRepository->all();
return $this->json([
'cities' => $cities
]);
}
}
Inside the controller, we fetch all data using the CityRepository. The data transformed into JSON with the json helper.
$ symfony serve
We start the web server and locate to the localhost:8000/city.
In the following example, we send a JSON response from a Laravel application.
$ laravel new larajson $ cd larajson
We create a new Laravel application.
.env
… DB_CONNECTION=sqlite DB_DATABASE=/tmp/ydb.db …
We define the connection and the database file.
$ touch /tmp/ydb.db
We create the database file.
$ php artisan make:migration create_cities_table Created Migration: 2020_07_25_101535_create_cities_table
A new migration for the cities table is created.
database/migrations/2020_07_25_101535_create_cities_table.php
<?php
use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema;
class CreateCitiesTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create(‘cities’, function (Blueprint $table) { $table->id(); $table->string(’name’); $table->integer(‘population’); }); }
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('cities');
}
}
In the migration file, we create a schema for the cities table.
$ php artisan migrate
We run the migrations.
$ php artisan make:seeder CitySeeder
We create a data seeder for our database.
database/seeds/CitySeeder.php
<?php
use Illuminate\Database\Seeder;
class CitySeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run() { DB::table(‘cities’)->insert([ [’name’ => ‘Bratislava’, ‘population’ => 432000], [“name” => “Budapest”, “population” => 1759000], [“name” => “Prague”, “population” => 1280000], [“name” => “Warsaw”, “population” => 1748000], [“name” => “Los Angeles”, “population” => 3971000], [“name” => “New York”, “population” => 8550000], [“name” => “Edinburgh”, “population” => 464000], [“name” => “Berlin”, “population” => 3671000] ]); } }
The seeder inserts eight rows into the table.
$ php artisan db:seed –class=CitySeeder
We execute the seeder.
routes/web.php
<?php
use Illuminate\Support\Facades\Route; use Illuminate\Http\JsonResponse;
Route::get(’/city’, function (): JsonResponse {
$cities = DB::table('cities')->get();
return response()->json([
'cities' => $cities
]);
});
Inside the route, we select all data from the database and return it as JSON with the json helper.
$ php artisan serve
We run the web server.
$ curl localhost:8000/city {“cities”:[{“id”:“1”,“name”:“Bratislava”,“population”:“432000”}, {“id”:“2”,“name”:“Budapest”,“population”:“1759000”}, {“id”:“3”,“name”:“Prague”,“population”:“1280000”}, {“id”:“4”,“name”:“Warsaw”,“population”:“1748000”}, {“id”:“5”,“name”:“Los Angeles”,“population”:“3971000”}, {“id”:“6”,“name”:“New York”,“population”:“8550000”}, {“id”:“7”,“name”:“Edinburgh”,“population”:“464000”}, {“id”:“8”,“name”:“Berlin”,“population”:“3671000”}]}
We get the data with the curl tool.
Symfony provides the HttpClient component which enables us to create HTTP requests in PHP. We can also send JSON data.
$ composer req symfony/http-client
We install the symfony/http-client component.
send_json_req.php
<?php
require(‘vendor/autoload.php’);
use Symfony\Component\HttpClient\HttpClient;
$httpClient = HttpClient::create(); $response = $httpClient->request(‘GET’, ‘http://localhost:8000/greet’, [ ‘json’ => [ ’name’ => ‘Lucia’, ‘message’ => ‘Cau’ ] ]);
$content = $response->getContent(); echo $content . “\n”;
The example sends a GET request with a JSON payload.
src/Controller/GreetController.php
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Request;
class GreetController extends AbstractController { /** * @Route("/greet", name=“greet”) */ public function index(Request $request): Response { $params = []; if ($data = $request->getContent()) { $params = json_decode($data, true); }
$msg = "{$params['name']} says {$params['message']}";
$textResponse = new Response($msg , 200);
$textResponse->headers->set('Content-Type', 'text/plain');
return $textResponse;
}
}
In the GreetController, we process the JSON data and generate a text message, which is returned to the client.
$ php send_json_req.php Lucia says Cau
In this article we have worked with JSON data in plain PHP, Symfony, Slim, and Laravel.
My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.
List all PHP tutorials.