JSON
JSON is how web services exchange data, and PHP converts to and from it with two functions.
json_encode
<?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";| PHP | JSON |
|---|---|
| associative array | object {...} |
| list (keys 0, 1, 2...) | array [...] |
| string, int, float | string, number |
true, false, null | true, false, null |
Useful flags
<?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 listJSON_PRETTY_PRINTadds line breaks and indentation for humans.JSON_UNESCAPED_UNICODEkeeps characters like ₹ readable instead of₹, andJSON_UNESCAPED_SLASHESstops/from becoming\/.- Combine flags with
|. - An array whose keys aren't exactly 0, 1, 2... becomes a JSON object. After filtering an array,
array_valuesturns it back into a list.
json_decode
<?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
$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.3Plain 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
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
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.