JSON (JavaScript Object Notation) is the language web services use to talk to each other. When a weather app asks a server for today's forecast, when a shop's JavaScript loads more products without refreshing the page, or when a payment service reports that a payment succeeded, the data almost always travels as JSON.
JSON looks a lot like PHP's arrays: objects with named keys in curly braces, lists in square brackets, plus strings, numbers, true, false and null. PHP converts between the two with just two functions: json_encode() turns PHP data into JSON text, and json_decode() turns JSON text back into PHP data.
In this lesson you'll encode and decode JSON, handle invalid JSON safely, read JSON from a file and a web API, and write a tiny API endpoint of your own that returns JSON for JavaScript to use. It ties together the arrays and file handling lessons.
json_encode: PHP to JSON
$product = ['name' => 'Desk lamp', 'price' => 24.5, 'in_stock' => true];
echo json_encode($product);
// {"name":"Desk lamp","price":24.5,"in_stock":true}- Associative arrays become JSON objects
{ }; indexed arrays (0, 1, 2...) become JSON arrays[ ]. true,falseandnullbecome their JSON equivalents.- Add flags for nicer output:
JSON_PRETTY_PRINTadds line breaks and indentation, andJSON_UNESCAPED_UNICODEandJSON_UNESCAPED_SLASHESkeep characters like é and / readable.
Combine flags with |: json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES).
json_decode: JSON to PHP
$json = '{"name":"Ana","scores":[82,91]}';
$data = json_decode($json, true);
echo $data['name']; // Ana
echo $data['scores'][1]; // 91The second argument, true, gives you associative arrays, which most PHP code finds easiest. Without it, objects become stdClass objects and you read them with arrows: $data->name. Pick one style and use it consistently.
Objects, empty arrays and JsonSerializable
json_encode turns an object into a JSON object using only its public properties; private and protected ones are left out. To control exactly what an object looks like as JSON, implement the JsonSerializable interface:
class Product implements JsonSerializable {
public function __construct(private string $name, private float $price) {}
public function jsonSerialize(): array {
return ['name' => $this->name, 'price' => round($this->price, 2)];
}
}
echo json_encode(new Product('Pen', 1.2)); // {"name":"Pen","price":1.2}Empty arrays need a little care. PHP can't tell whether an empty array is meant as a list or an object, so json_encode([]) gives []. If the receiving program expects an object, use (object) [] or the JSON_FORCE_OBJECT flag, both of which give {}. Clients written in strongly typed languages often break when the same field is sometimes [] and sometimes {}.
Handling invalid JSON
JSON from outside your program might be broken or incomplete. By default json_decode simply returns null, which is easy to miss. The modern, safer way is to ask PHP to throw an exception:
try {
$data = json_decode($json, true, 512, JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
echo "Invalid JSON: " . $e->getMessage();
}The 512 is the maximum nesting depth, which you'll rarely need to change. Exceptions are covered fully in the exceptions lesson.
Calling an API and returning JSON
Reading JSON from another service can be as simple as file_get_contents($url), although real projects usually use the cURL extension or a library such as Guzzle for timeouts and headers.
To build your own small API endpoint, set the right header and echo JSON:
header('Content-Type: application/json');
echo json_encode(['status' => 'ok', 'items' => $items]);JavaScript on your page can then load it with fetch('/api/products.php'), exactly as in the JavaScript fetch lesson. Use http_response_code(404) or similar to signal errors properly.
PHP JSON Syntax
JSON functions
$json = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
$data = json_decode($json, true, 512, JSON_THROW_ON_ERROR);
header('Content-Type: application/json');
echo json_encode(['data' => $items]);PHP JSON Summary
- JSON is the standard text format for exchanging data between programs.
json_encodeturns PHP arrays into JSON; flags likeJSON_PRETTY_PRINTformat it.json_decode($json, true)gives associative arrays; withouttrueyou get objects.- Use
JSON_THROW_ON_ERRORand catchJsonExceptionfor invalid JSON. - Send
Content-Type: application/jsonwhen returning JSON from an endpoint.
PHP JSON Examples
Each example shows the code, the output it produces and what each part does.
Encoding a list of products
<?php
$products = [
['name' => 'Pen', 'price' => 1.2, 'tags' => ['stationery']],
['name' => 'Café mug', 'price' => 8.5, 'tags' => []],
];
echo json_encode($products), "\n\n";
echo json_encode($products[1], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);[{"name":"Pen","price":1.2,"tags":["stationery"]},{"name":"Caf\u00e9 mug","price":8.5,"tags":[]}]
{
"name": "Café mug",
"price": 8.5,
"tags": []
}Line-by-line explanation
- Lines 2 to 5An indexed array of associative arrays becomes a JSON array of objects.
- Line 7By default, non-English characters are escaped as \u codes.
- Line 8The flags make the output readable and keep é as it is.
Decoding and using data
<?php
$json = '{"city":"Lisbon","days":[{"day":"Mon","temp":24},{"day":"Tue","temp":27},{"day":"Wed","temp":22}]}';
$forecast = json_decode($json, true);
$temps = array_column($forecast['days'], 'temp');
echo "Forecast for {$forecast['city']}\n";
foreach ($forecast['days'] as $d) {
echo "{$d['day']}: {$d['temp']}°C\n";
}
echo "Warmest: " . max($temps) . "°C";Forecast for Lisbon
Mon: 24°C
Tue: 27°C
Wed: 22°C
Warmest: 27°CLine-by-line explanation
- Line 4true turns every JSON object into an associative array.
- Line 5array_column pulls the temp value out of each day.
- Lines 8 to 10Nested data is reached with one key after another.
A tiny JSON API endpoint
The browser requested /api/products.php?max=10.
<?php
// api/products.php
header('Content-Type: application/json');
$products = [
['name' => 'Pen', 'price' => 1.2],
['name' => 'Notebook', 'price' => 3.5],
['name' => 'Lamp', 'price' => 24.5],
];
$max = filter_var($_GET['max'] ?? '', FILTER_VALIDATE_FLOAT);
if ($max === false) {
http_response_code(400);
echo json_encode(['error' => 'max must be a number']);
exit;
}
$cheap = array_values(array_filter($products, fn($p) => $p['price'] <= $max));
echo json_encode(['count' => count($cheap), 'data' => $cheap]);{"count":2,"data":[{"name":"Pen","price":1.2},{"name":"Notebook","price":3.5}]}Line-by-line explanation
- Line 3Tell the browser it's receiving JSON.
- Lines 11 to 16Validate the input and return a 400 error in JSON if it's wrong.
- Line 18array_filter keeps cheap products; array_values renumbers them so they encode as a JSON array.
Common PHP JSON Mistakes
Forgetting true in json_decode
$data = json_decode($json);
echo $data['name']; // Error: cannot use object as array$data = json_decode($json, true);
echo $data['name'];Ignoring invalid JSON
$data = json_decode($input, true);
echo count($data['items']); // fails confusingly if $input was brokentry {
$data = json_decode($input, true, 512, JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
http_response_code(400);
exit(json_encode(['error' => 'Invalid JSON']));
}Filtered arrays turning into objects
echo json_encode(array_filter([1, 5, 8], fn($n) => $n > 2)); // {"1":5,"2":8}echo json_encode(array_values(array_filter([1, 5, 8], fn($n) => $n > 2))); // [5,8]array_filter keeps the original keys, so the array is no longer 0, 1, 2 and encodes as an object.
PHP JSON in Real Projects
JSON in PHP projects
Shops send order data to payment services as JSON, mobile apps talk to PHP back ends through JSON APIs, and WordPress has a built-in REST API that returns posts and pages as JSON. Configuration files and translation files are also often stored as JSON and loaded with json_decode.
PHP JSON FAQ
How do I read JSON sent in a request body?
JSON posted by JavaScript's fetch or another API doesn't appear in $_POST. Read the raw body with file_get_contents('php://input') and decode it: $data = json_decode($body, true, 512, JSON_THROW_ON_ERROR);. Then validate the fields as you would form input.
Why does json_encode return false?
Most often because a string contains invalid UTF-8, for example text read from an old file in another encoding. json_last_error_msg() explains the problem, and JSON_THROW_ON_ERROR turns it into an exception. Convert the text to UTF-8 with mb_convert_encoding, or use JSON_INVALID_UTF8_SUBSTITUTE to replace broken characters.
How do I check whether a string is valid JSON?
In PHP 8.3 and later, json_validate($text) returns true or false without building the decoded data, which saves memory for large inputs. In earlier versions, decode it with JSON_THROW_ON_ERROR inside a try block and catch JsonException.
What is the difference between JSON and serialize()?
JSON is a language-independent format that JavaScript, Python and every other language can read. serialize() produces a PHP-specific format that can recreate PHP objects, and unserialize() on untrusted data is a security risk. Use JSON for APIs, files and anything stored long term.
Why does a decimal look slightly wrong in my JSON?
Floats are stored in binary, so 0.1 + 0.2 encodes as 0.30000000000000004. Round values before encoding, round($total, 2), or send money as whole cents or as strings formatted with number_format, so the receiving program shows the exact amount.
PHP JSON Exercises
Answer each one and check it instantly. If you get stuck, open the hint before the answer.
Complete the code that turns $data into JSON text.
echo ($data);
What does this output?
echo json_encode(['a' => 1, 'b' => [2, 3]]);
What does this output?
$d = json_decode('{"user":{"name":"Leo","age":15}}', true);
echo $d['user']['age'] + 1;
Which header should a PHP script send when it returns JSON?
How can you make json_decode throw an exception on invalid input?
PHP JSON Quiz
5 questions to check what you learned.
What is JSON mainly used for?
- Styling web pages
- Exchanging data between programs and services
- Storing passwords
- Compressing images
What does json_decode return for invalid JSON by default?
- An empty array
- false
- An exception
- null
What does JSON_PRETTY_PRINT do?
- Removes spaces
- Adds line breaks and indentation so JSON is easy to read
- Sorts the keys
- Converts numbers to strings
What PHP type does
json_decode($json, true)use for JSON objects?- stdClass objects
- Strings
- Indexed arrays only
- Associative arrays
Why might
json_encode(array_filter($list))produce an object instead of an array?- array_filter returns a string
- json_encode always returns objects
- array_filter keeps original keys, so they're no longer 0, 1, 2 in order
- Filtered arrays can't be encoded