01 · THE IDEAREAD → TRY → LEARN
JSON is a plain-text format for exchanging structured data between programs. PHP gives you two main tools: json_encode() turns a PHP value into JSON text, and json_decode() turns JSON text back into a PHP value. This lesson builds from the happy path to reliable error handling.
Encoding arrays
PHP arrays map onto two JSON shapes. An array with sequential integer keys starting at 0 becomes a JSON array. An array with string keys becomes a JSON object. Booleans, integers, floats, strings and null map to their JSON counterparts.
$user = ['name' => 'Ada', 'langs' => ['PHP', 'SQL'], 'active' => true, 'score' => null];
echo json_encode($user, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;{"name":"Ada","langs":["PHP","SQL"],"active":true,"score":null}
The two flags keep non-ASCII characters and slashes readable instead of escaping them. They change only the text, not the meaning.
Decoding into arrays
The signature is json_decode(string $json, ?bool $associative = null, int $depth = 512, int $flags = 0): mixed. The input must be UTF-8. If you pass true for $associative, JSON objects become associative arrays. If you pass false, or leave the default with no flags, they become stdClass objects. Most application code that treats JSON as plain data uses true, because arrays are easier to test and compare.
$json = '{"id":7,"tags":["a","b"],"meta":{"ok":true}}';
$data = json_decode($json, true);
echo $data['id'], PHP_EOL;
echo count($data['tags']), PHP_EOL;
echo json_encode($data['meta']['ok']), PHP_EOL;7 2 true
The return type is mixed, because valid JSON can be an object, array, string, number, boolean or null. Never assume the result is an array without checking.
The trouble with null
By default, json_decode() returns null when the text cannot be decoded, or when the nesting is deeper than $depth. But the valid JSON text null also decodes to null. A plain null check therefore cannot distinguish a failure from a legitimate value.
The clean fix is the JSON_THROW_ON_ERROR flag. With it, decoding problems throw a JsonException instead of returning null, and you handle them with try and catch like any other exception.
try {
json_decode("{ 'bar': 'baz' }", true, 512, JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
echo get_class($e), ': ', $e->getMessage(), PHP_EOL;
}JsonException: Syntax error
Single quotes are valid in JavaScript source but not in JSON, so this input is a syntax error. Other common causes are unquoted keys and trailing commas. The older alternative is to call json_last_error() or json_last_error_msg() after decoding, but that depends on hidden global state and is easy to forget.
Other details worth knowing
$depthmust be greater than 0. A value outside the allowed range throws aValueError.- Very large integers that do not fit in a PHP integer become floats. The
JSON_BIGINT_AS_STRINGflag keeps them as strings instead. - Object keys that are not valid PHP property names, such as
foo-bar, are still reachable with associative arrays, which is another reason to prefertrue. - Decoding then re-encoding does not always give back the identical text. Whitespace and key escaping may differ, and an empty JSON object and an empty JSON array both decode to
[]in associative mode.
Common mistakes
- Testing the decoded value with
if (!$data). This treats0,"",falseand an empty array as failures. - Using
??orisset()to read a key whose value may benull. Both treat a presentnullthe same as a missing key. Usearray_key_exists()when the difference matters. - Forgetting that the result may not be an array at all. The JSON text
5decodes to an integer, so indexing it as an array would be wrong.
Exercise contract
Write safeJsonField(string $json, string $key, mixed $default): mixed. It decodes $json as an associative structure and returns the top-level value stored under $key. If the JSON is malformed, is not an object or array, or lacks the key, it returns $default. A key that is present with a falsy value or null must be returned as is, not replaced by the default. The tests check the returned values, not printed output.
Recap
Use json_encode() to produce JSON text and json_decode($json, true) to get arrays. Add JSON_THROW_ON_ERROR so that malformed input becomes a JsonException you can catch. Remember that null is both a valid result and the old failure signal, and check types before using the decoded value.
Arrays · Exceptions
- Encode an array as JSON
- Decode and handle malformed JSON deterministically