CodeMIRAI
0 XP

JSON

2 min read 5 runnable examples Quiz included

JSON is how web services exchange data, and PHP converts to and from it with two functions.

json_encode

PHP
<?php
$course = [
    "title" => "PHP",
    "lessons" => 15,
    "free" => true,
    "tags" => ["web", "backend"],
    "rating" => null,
];
echo json_encode($course), "\n";
echo json_encode($course, JSON_PRETTY_PRINT), "\n";
PHPJSON
associative arrayobject {...}
list (keys 0, 1, 2...)array [...]
string, int, floatstring, number
true, false, nulltrue, false, null

Useful flags

PHP
<?php
$data = ["price" => "₹499", "url" => "https://codemirai.com/learn/php/"];
echo json_encode($data), "\n";
echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
echo json_encode([1 => "a", 2 => "b"]), "\n";               // keys don't start at 0: an object
echo json_encode(array_values([1 => "a", 2 => "b"])), "\n"; // a proper list
  • JSON_PRETTY_PRINT adds line breaks and indentation for humans.
  • JSON_UNESCAPED_UNICODE keeps characters like ₹ readable instead of ₹, and JSON_UNESCAPED_SLASHES stops / from becoming \/.
  • Combine flags with |.
  • An array whose keys aren't exactly 0, 1, 2... becomes a JSON object. After filtering an array, array_values turns it back into a list.

json_decode

PHP
<?php
$json = '{"user": {"name": "Asha", "langs": ["PHP", "SQL"]}, "active": true}';

$obj = json_decode($json);                 // stdClass objects
echo $obj->user->name, " knows ", $obj->user->langs[0], "\n";

$arr = json_decode($json, true);           // associative arrays
echo $arr["user"]["name"], " knows ", count($arr["user"]["langs"]), " languages\n";
var_dump($arr["active"]);

By default, JSON objects become PHP objects, read with ->. Pass true as the second argument to get associative arrays instead, which many people find easier to work with.

Invalid JSON

PHP
<?php
$bad = '{"name": "Asha",}';                  // a trailing comma isn't allowed in JSON

var_dump(json_decode($bad));                 // NULL
echo json_last_error_msg(), "\n";

try {
    json_decode($bad, true, flags: JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
    echo "Could not read the data: ", $e->getMessage(), "\n";
}

var_dump(json_validate('{"ok": true}'), json_validate($bad));    // PHP 8.3

Plain json_decode returns null for invalid input, which is easy to miss, and indistinguishable from the valid JSON null. JSON_THROW_ON_ERROR makes it throw an exception instead, which is the safer habit.

Objects that control their JSON

PHP
<?php
class User implements JsonSerializable {
    public function __construct(
        private string $name,
        private string $email,
        private string $passwordHash,
    ) {}

    public function jsonSerialize(): array {
        return ["name" => $this->name, "email" => $this->email];   // never the password hash
    }
}

$u = new User("Asha", "asha@example.com", "\$2y\$10\$abc...");
echo json_encode($u), "\n";

Implementing JsonSerializable lets a class decide exactly what goes into its JSON, which is essential for keeping secrets like password hashes out of API responses.

A small JSON API

PHP
<?php
header("Content-Type: application/json");

$input = json_decode(file_get_contents("php://input"), true) ?? [];  // the request body
$name = trim($input["name"] ?? "");

if ($name === "") {
    http_response_code(422);
    echo json_encode(["error" => "name is required"]);
    exit;
}

echo json_encode(["message" => "Hello, $name", "time" => date(DATE_ATOM)]);

A JSON endpoint sets the Content-Type header, reads the request body from php://input, and answers with json_encode, plus a suitable HTTP status code when something's wrong.

Finished this lesson?Mark it complete to earn +20 XP and move your progress on.