Working with JSON
JSON is the universal language of web APIs. PHP gives you exactly two functions for it — json_encode to send data out and json_decode to read it back in. Master those two, plus error handling, and you can talk to any API on the internet.
Learn Working with JSON in our free PHP course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick recall.
Part of the free Php course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
What You'll Learn in This Lesson
1️⃣ Encoding to JSON
json_encode($value) serialises a PHP value into a JSON string. An associative array becomes a JSON object { } , a list array becomes a JSON array [ ] , and scalars map directly. Pass the JSON_PRETTY_PRINT flag for nicely indented output when a human needs to read it.
2️⃣ Decoding from JSON
json_decode($string) goes the other way. With one argument you get a stdClass object (access with -> ); pass true as the second argument to get an associative array instead (access with [] ). Most PHP code uses the array form — it's easier to loop and pass around.
3️⃣ Handling Invalid JSON
Here's a trap: when JSON is malformed, json_decode returns null silently — and null is also a valid JSON value, so a bare null-check is ambiguous. Either inspect json_last_error() , or — much cleaner on modern PHP — pass JSON_THROW_ON_ERROR so bad input throws a JsonException you can catch.
4️⃣ The Round-Trip
Almost every API endpoint is a round-trip: take a PHP object, json_encode it for the response, then on the next request json_decode the body back into PHP. Note that json_encode serialises only an object's public properties — private and protected ones are skipped (you'd implement JsonSerializable to customise that).
Now you try — fill in each ___ using the 👉 hint, then run it and check against the Output panel.
🧩 Reorder Challenge
These lines round-trip a value through JSON — but they're scrambled. Put them in the order that prints Ada .
Build the array ( B ), encode it to a JSON string ( D ), decode that string back into an array ( C ), then read the value out ( A ). Each step depends on the variable produced by the one before it.
🧠 Quick Recall — Predict the Output
{"a":1,"b":true} — string keys produce a JSON object, and the PHP true becomes JSON true .
object — without the true flag, json_decode returns a stdClass object. You'd read $x->n , not $x['n'] .
NULL — invalid JSON makes json_decode return null silently. That's why you check json_last_error() or use JSON_THROW_ON_ERROR .
Common Errors (and the fix)
- "Trying to access array offset on value of type null" — json_decode returned null on bad JSON. Check the error before using the result.
- You used -> but got an "array" error (or vice versa) — you passed true (array) but accessed with -> . Match the access style to the decode mode.
- A private property is missing from your JSON — json_encode only includes public properties. Implement JsonSerializable to control output.
- Accented characters show as é — that's valid JSON, but add JSON_UNESCAPED_UNICODE if you want them literal.
Pro Tips
- 💡 Always decode with true unless you specifically want an object — arrays are easier to work with in PHP.
- 💡 Add JSON_THROW_ON_ERROR so bad input fails loudly with an exception instead of a silent null .
- 💡 Combine flags with | : JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE is a great default for API responses.
📋 Quick Reference — JSON
Syntax
Example
What It Does
json_encode()
json_encode($arr)
PHP value → JSON string
JSON_PRETTY_PRINT
json_encode($a, JSON_PRETTY_PRINT)
Indented output
json_decode()
json_decode($s)
JSON → stdClass object
json_decode($s, true)
JSON → associative array
JSON_THROW_ON_ERROR
json_decode($s, true, 512, JSON_THROW_ON_ERROR)
Throw on bad JSON
json_last_error_msg()
Last error as text
JsonSerializable
jsonSerialize(): array
Customise encode output
Frequently Asked Questions
Mini-Challenge: API Response
No code is filled in this time — just a brief and an outline. Write it yourself, run it on onecompiler.com/php or your own machine, then check your result against the expected output in the comments.
🎉 Lesson Complete!
- ✅ json_encode turns PHP values into JSON; JSON_PRETTY_PRINT formats them
- ✅ json_decode($s) gives an object; add true for an array
- ✅ Bad JSON returns null silently — check the error or use JSON_THROW_ON_ERROR
- ✅ Only public properties serialise; use JsonSerializable to customise
- ✅ The PHP → JSON → PHP round-trip is the heart of every API
- ✅ Next lesson: Traits — share methods across unrelated classes
Practice quiz
What does json_decode return by default (with no second argument)?
- An associative array
- A string
- A stdClass object
- null
Answer: A stdClass object. By default json_decode returns a stdClass object, so you read properties with the arrow: $data->name. Pass true for an array.
What does json_decode($json, true) return?
- An associative array
- A stdClass object
- A JSON string
- false
Answer: An associative array. Passing true as the second argument gives an associative array, read with brackets: $data['name'].
What does echo json_encode(['a' => 1, 'b' => true]); print?
- {"a":1,"b":1}
String keys produce a JSON object, and the PHP boolean true becomes JSON true (not 1).
What does json_decode return when given invalid JSON?
- false
- null (silently)
- An empty array
- It throws by default
Answer: null (silently). Invalid JSON makes json_decode return null silently — which is why you check json_last_error() or use JSON_THROW_ON_ERROR.
Which flag makes json_decode throw a JsonException on bad input instead of returning null?
- JSON_THROW_ON_ERROR
- JSON_PRETTY_PRINT
- JSON_UNESCAPED_UNICODE
- JSON_ERROR_NONE
Answer: JSON_THROW_ON_ERROR. JSON_THROW_ON_ERROR makes malformed input throw a JsonException you can catch, rather than silently returning null.
Which object properties does json_encode serialise by default?
- All properties
- Only private properties
- Only public properties
- Only properties listed in a __toString
Answer: Only public properties. json_encode serialises only public properties; private and protected ones are skipped. Implement JsonSerializable to customise.
Which flag makes json_encode output indented, human-readable JSON?
- JSON_INDENT
- JSON_PRETTY_PRINT
- JSON_FORMAT
- JSON_HUMAN
Answer: JSON_PRETTY_PRINT. JSON_PRETTY_PRINT formats the output with indentation for readability.
How do you combine multiple json_encode flags?
- With commas
- With +
- You can only pass one flag
- With the bitwise OR operator |
Answer: With the bitwise OR operator |. Flags combine with bitwise OR, e.g. json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE).
Why is a bare null check after json_decode ambiguous?
- null is never returned
- The literal JSON value null also decodes to null
- json_decode returns false on error
- null means success
Answer: The literal JSON value null also decodes to null. json_decode returns null both for the literal JSON null and for invalid JSON, so use json_last_error() to tell them apart.
Which interface lets you customise exactly what an object encodes to?
- Serializable
- Stringable
- JsonSerializable
- ArrayAccess
Answer: JsonSerializable. Implement JsonSerializable and define jsonSerialize() to return the exact array or value you want encoded.
Continue this course
- Previous: Regular Expressions (preg)
- Next: Traits