Lesson 26 of 100
JSON12 min5 checksPHP 8.5

Encode and Decode JSON Safely

Turn PHP arrays into JSON text, decode JSON back into arrays, and report malformed input predictably with JsonException.

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.

Example
<?php
$user = ['name' => 'Ada', 'langs' => ['PHP', 'SQL'], 'active' => true, 'score' => null];
echo json_encode($user, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;
Output
{"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.

Example
<?php
$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;
Output
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.

Example
<?php
try {
    json_decode("{ 'bar': 'baz' }", true, 512, JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
    echo get_class($e), ': ', $e->getMessage(), PHP_EOL;
}
Output
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

  • $depth must be greater than 0. A value outside the allowed range throws a ValueError.
  • Very large integers that do not fit in a PHP integer become floats. The JSON_BIGINT_AS_STRING flag 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 prefer true.
  • 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

  1. Testing the decoded value with if (!$data). This treats 0, "", false and an empty array as failures.
  2. Using ?? or isset() to read a key whose value may be null. Both treat a present null the same as a missing key. Use array_key_exists() when the difference matters.
  3. Forgetting that the result may not be an array at all. The JSON text 5 decodes 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.

Before you start

Arrays · Exceptions

You’ll practice
  • Encode an array as JSON
  • Decode and handle malformed JSON deterministically
Your task

Make safeJsonField() pass all 5 checks. Run your code as often as you like, then check your answer.

exercise.phpSaved in this browserPHP 8.5
CONSOLE & CHECKS● Ready

Ready when you are

Your output will appear here.
Make it work. Then make it pass.

PHP loads on your first run. Each check starts fresh. Your code stays in this browser; clearing site data removes your progress. A check or the task looks wrong? Report a problem with this exercise.