JSON7 min readExamples run on PHP 8.5.10

json_decode()

Learn how json_decode() converts JSON text into PHP arrays, objects and scalars in PHP 8.4, and how to handle invalid input, depth limits and big integers.

Signature

json_decode(string $json, ?bool $associative = null, int $depth = 512, int $flags = 0): mixed
Available since PHP 5.2.07.48.08.18.28.38.48.5All versions →

Purpose

json_decode() takes a JSON-encoded string and converts it into a PHP value. You use it whenever data arrives as JSON text, for example a request body, a stored settings string or an API response already held in memory. The result can be an array, an object, a string, an int, a float, a bool or null, depending on what the JSON contains.

Signature

Parameters and defaults

  • $json: the JSON text. It must be UTF-8. PHP accepts a slightly wider syntax than the strict RFC, but you should send strict JSON.
  • $associative: with true, JSON objects become associative arrays. With false, they become stdClass objects. With the default null, the choice depends on whether JSON_OBJECT_AS_ARRAY is set in $flags. Without that flag you get objects.
  • $depth: the maximum nesting depth, 512 by default. It must be greater than 0 and no larger than 2147483647.
  • $flags: a bitmask. The documented flags are JSON_BIGINT_AS_STRING, JSON_INVALID_UTF8_IGNORE, JSON_INVALID_UTF8_SUBSTITUTE, JSON_OBJECT_AS_ARRAY and JSON_THROW_ON_ERROR.

Return value and failure cases

The return type is mixed. The literals true, false and null decode to their PHP counterparts. On failure the function returns null when the text cannot be decoded or is nested deeper than $depth.

This creates an ambiguity, because the valid JSON text null also decodes to null. To tell the two cases apart, either call json_last_error() or json_last_error_msg() right after the call, or pass JSON_THROW_ON_ERROR. That flag makes failures throw a JsonException instead of returning null.

An out-of-range $depth throws a ValueError.

Example 1: decoding to an associative array

Pass true as the second argument when you want to work with plain arrays.

Example
<?php
$json = '{"name":"Ada","langs":["PHP","SQL"],"active":true,"score":9.5}';
$data = json_decode($json, true);
echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;
echo $data['langs'][1], PHP_EOL;
var_dump($data['active']);
Output
{"name":"Ada","langs":["PHP","SQL"],"active":true,"score":9.5}
SQL
bool(true)

JSON arrays become PHP lists, JSON objects become associative arrays, and true stays a real boolean.

Example 2: decoding to objects

Without the second argument, JSON objects become stdClass instances. Keys that are not valid PHP identifiers, such as ones containing a hyphen, are read with braces and quotes.

Example
<?php
$json = '{"foo-bar":12345,"nested":{"x":1}}';
$obj = json_decode($json);
echo $obj->{'foo-bar'}, PHP_EOL;
echo get_class($obj->nested), PHP_EOL;
echo $obj->nested->x, PHP_EOL;
Output
12345
stdClass
1

Example 3: failing loudly with JSON_THROW_ON_ERROR

The throw flag removes the ambiguity between invalid JSON and the literal null.

Example
<?php
function decodeOrMessage(string $json): string
{
    try {
        $value = json_decode($json, true, 512, JSON_THROW_ON_ERROR);
        return json_encode($value);
    } catch (JsonException $e) {
        return 'error: ' . $e->getMessage();
    }
}

echo decodeOrMessage('{"ok":true}'), PHP_EOL;
echo decodeOrMessage("{'ok':true}"), PHP_EOL;
echo decodeOrMessage('null'), PHP_EOL;
Output
{"ok":true}
error: Syntax error
null

The single-quoted text is not valid JSON, so it throws. The text null is valid and decodes without error.

Edge cases

  • Depth: every level of nesting counts toward $depth. In the manual's example, a structure with three nested arrays holding strings decodes with a depth of 4 but fails with a depth of 3, reporting "Maximum stack depth exceeded".
  • Large integers: an integer too large for a PHP int is decoded as a float and loses precision. Pass JSON_BIGINT_AS_STRING to receive it as a string instead.
  • Scalars at the top level: a JSON document may be just a number, a string or null. The result is then not an array or object.
  • Empty input: an empty string is not valid JSON, so without the throw flag you get null and an error code.
  • Encoding: the input must be UTF-8. The flags JSON_INVALID_UTF8_IGNORE and JSON_INVALID_UTF8_SUBSTITUTE control what happens to invalid byte sequences.

Common mistakes

  1. Writing JavaScript, not JSON. Single quotes, unquoted keys and trailing commas are all rejected. Names and string values need double quotes.
  2. Treating null as proof of failure. It may be a valid result. Check the error state or use JSON_THROW_ON_ERROR.
  3. Forgetting the second argument. Code written for arrays, like $data['name'], breaks on a stdClass object.
  4. Trusting the shape of the data. Decoded input can contain any type in any position, so check that keys exist and have the expected types before using them.
  5. Assuming large IDs survive. Numeric identifiers beyond the int range silently become floats unless you opt into strings.
  • json_encode() converts a PHP value into JSON text.
  • json_last_error() returns the error code of the last JSON operation.
  • json_last_error_msg() returns a readable message for that error.
  • json_validate() checks whether a string is valid JSON, which is useful when you do not need the decoded value.

Recap

Use json_decode() to turn UTF-8 JSON text into PHP values. Choose arrays with true or objects by default, and raise $depth only if you genuinely need deeper nesting. Prefer JSON_THROW_ON_ERROR so that a bad document is never confused with a valid null. Remember that big integers become floats unless you request strings.

Tested examples

Decode a JSON object into an associative array
<?php
$json = '{"name":"Ada","langs":["PHP","SQL"],"active":true,"score":9.5}';
$data = json_decode($json, true);
echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), PHP_EOL;
echo $data['langs'][1], PHP_EOL;
var_dump($data['active']);
Output
{"name":"Ada","langs":["PHP","SQL"],"active":true,"score":9.5}
SQL
bool(true)
Decode into stdClass objects and read an unusual key
<?php
$json = '{"foo-bar":12345,"nested":{"x":1}}';
$obj = json_decode($json);
echo $obj->{'foo-bar'}, PHP_EOL;
echo get_class($obj->nested), PHP_EOL;
echo $obj->nested->x, PHP_EOL;
Output
12345
stdClass
1
Handle invalid JSON with JSON_THROW_ON_ERROR
<?php
function decodeOrMessage(string $json): string
{
    try {
        $value = json_decode($json, true, 512, JSON_THROW_ON_ERROR);
        return json_encode($value);
    } catch (JsonException $e) {
        return 'error: ' . $e->getMessage();
    }
}

echo decodeOrMessage('{"ok":true}'), PHP_EOL;
echo decodeOrMessage("{'ok':true}"), PHP_EOL;
echo decodeOrMessage('null'), PHP_EOL;
Output
{"ok":true}
error: Syntax error
null