309

This is intended to be a general reference question and answer covering many of the never-ending "How do I access data in my JSON?" questions. It is here to handle the broad basics of decoding JSON in PHP and accessing the results.

I have the JSON:

{
    "type": "donut",
    "name": "Cake",
    "toppings": [
        { "id": "5002", "type": "Glazed" },
        { "id": "5006", "type": "Chocolate with Sprinkles" },
        { "id": "5004", "type": "Maple" }
    ]
}

How do I decode this in PHP and access the resulting data?

3

3 Answers 3

609
+500

Intro

First off you have a string. JSON is not an array, an object, or a data structure. JSON is a text-based serialization format - so a fancy string, but still just a string. Decode it in PHP by using json_decode().

 $data = json_decode($json);

Therein you might find:

These are the things that can be encoded in JSON. Or more accurately, these are PHP's versions of the things that can be encoded in JSON.

There's nothing special about them. They are not "JSON objects" or "JSON arrays." You've decoded the JSON - you now have basic everyday PHP types.

Objects will be instances of stdClass, a built-in class which is just a generic thing that's not important here.


Accessing object properties

You access the properties of one of these objects the same way you would for the public non-static properties of any other object, e.g. $object->property.

$json = '
{
    "type": "donut",
    "name": "Cake"
}';

$yummy = json_decode($json);

echo $yummy->type; //donut

Accessing array elements

You access the elements of one of these arrays the same way you would for any other array, e.g. $array[0].

$json = '
[
    "Glazed",
    "Chocolate with Sprinkles",
    "Maple"
]';

$toppings = json_decode($json);

echo $toppings[1]; //Chocolate with Sprinkles

Iterate over it with foreach.

foreach ($toppings as $topping) {
    echo $topping, "\n";
}

Glazed
Chocolate with Sprinkles
Maple

Or mess about with any of the bazillion built-in array functions.


Accessing nested items

The properties of objects and the elements of arrays might be more objects and/or arrays - you can simply continue to access their properties and members as usual, e.g. $object->array[0]->etc.

$json = '
{
    "type": "donut",
    "name": "Cake",
    "toppings": [
        { "id": "5002", "type": "Glazed" },
        { "id": "5006", "type": "Chocolate with Sprinkles" },
        { "id": "5004", "type": "Maple" }
    ]
}';

$yummy = json_decode($json);

echo $yummy->toppings[2]->id; //5004

Passing true as the second argument to json_decode()

When you do this, instead of objects you'll get associative arrays - arrays with strings for keys. Again you access the elements thereof as usual, e.g. $array['key'].

$json = '
{
    "type": "donut",
    "name": "Cake",
    "toppings": [
        { "id": "5002", "type": "Glazed" },
        { "id": "5006", "type": "Chocolate with Sprinkles" },
        { "id": "5004", "type": "Maple" }
    ]
}';

$yummy = json_decode($json, true);

echo $yummy['toppings'][2]['type']; //Maple

Accessing associative array items

When decoding a JSON object to an associative PHP array, you can iterate both keys and values using the foreach (array_expression as $key => $value) syntax, eg

$json = '
{
    "foo": "foo value",
    "bar": "bar value",
    "baz": "baz value"
}';

$assoc = json_decode($json, true);
foreach ($assoc as $key => $value) {
    echo "The value of key '$key' is '$value'", PHP_EOL;
}

Prints

The value of key 'foo' is 'foo value'
The value of key 'bar' is 'bar value'
The value of key 'baz' is 'baz value'


Don't know how the data is structured

Read the documentation for whatever it is you're getting the JSON from.

Look at the JSON - where you see curly brackets {} expect an object, where you see square brackets [] expect an array.

Hit the decoded data with a print_r():

$json = '
{
    "type": "donut",
    "name": "Cake",
    "toppings": [
        { "id": "5002", "type": "Glazed" },
        { "id": "5006", "type": "Chocolate with Sprinkles" },
        { "id": "5004", "type": "Maple" }
    ]
}';

$yummy = json_decode($json);

print_r($yummy);

and check the output:

stdClass Object
(
    [type] => donut
    [name] => Cake
    [toppings] => Array
        (
            [0] => stdClass Object
                (
                    [id] => 5002
                    [type] => Glazed
                )

            [1] => stdClass Object
                (
                    [id] => 5006
                    [type] => Chocolate with Sprinkles
                )

            [2] => stdClass Object
                (
                    [id] => 5004
                    [type] => Maple
                )

        )

)

It'll tell you where you have objects, where you have arrays, along with the names and values of their members.

If you can only get so far into it before you get lost - go that far and hit that with print_r():

print_r($yummy->toppings[0]);
stdClass Object
(
    [id] => 5002
    [type] => Glazed
)

Take a look at it in this handy interactive JSON explorer.

Break the problem down into pieces that are easier to wrap your head around.


json_decode() returns null

This happens because either:

  1. The JSON consists entirely of just that, null.
  2. The JSON is invalid - check the result of json_last_error_msg or put it through something like JSONLint.
  3. It contains elements nested more than 512 levels deep. This default max depth can be overridden by passing an integer as the third argument to json_decode().

If you need to change the max depth you're probably solving the wrong problem. Find out why you're getting such deeply nested data (e.g. the service you're querying that's generating the JSON has a bug) and get that to not happen.


Object property name contains a special character

Sometimes you'll have an object property name that contains something like a hyphen - or at sign @ which can't be used in a literal identifier. Instead you can use a string literal within curly braces to address it.

$json = '{"@attributes":{"answer":42}}';
$thing = json_decode($json);

echo $thing->{'@attributes'}->answer; //42

If you have an integer as property see: How to access object properties with names like integers? as reference.


Someone put JSON in your JSON

It's ridiculous but it happens - there's JSON encoded as a string within your JSON. Decode, access the string as usual, decode that, and eventually get to what you need.

$json = '
{
    "type": "donut",
    "name": "Cake",
    "toppings": "[{ \"type\": \"Glazed\" }, { \"type\": \"Maple\" }]"
}';

$yummy = json_decode($json);
$toppings = json_decode($yummy->toppings);

echo $toppings[0]->type; //Glazed

Data doesn't fit in memory

If your JSON is too large for json_decode() to handle at once things start to get tricky. See:


How to sort it

See: Reference: all basic ways to sort arrays and data in PHP.

Sign up to request clarification or add additional context in comments.

1 Comment

just stumbled at this answer and found that the link to array.include-once.org is broken.
5
<?php
$jsonData = '{
    "type": "donut",
    "name": "Cake",
    "toppings": [
        { "id": "5002", "type": "Glazed" },
        { "id": "5006", "type": "Chocolate with Sprinkles" },
        { "id": "5004", "type": "Maple" }
    ]
}';

// Decode the JSON
$data = json_decode($jsonData, true);

// Access the data
$type = $data['type'];
$name = $data['name'];
$toppings = $data['toppings'];

// Access individual topping details
$firstTopping = $toppings[0];
$firstToppingId = $firstTopping['id'];
$firstToppingType = $firstTopping['type'];

// Print the data
echo "Type: $type\n";
echo "Name: $name\n";
echo "First Topping ID: $firstToppingId\n";
echo "First Topping Type: $firstToppingType\n";
?>

In this example, json_decode() is used to decode the JSON data into a PHP associative array. You can then access the individual elements of the array as you would with any PHP array.

Comments

-1

To decode JSON Text, PHP has the json_decode() function:

$ php -n --rf json_decode
Function [ <internal:json> function json_decode ] {

  - Parameters [4] {
    Parameter #0 [ <required> string $json ]
    Parameter #1 [ <optional> ?bool $associative = null ]
    Parameter #2 [ <optional> int $depth = 512 ]
    Parameter #3 [ <optional> int $flags = 0 ]
  }
  - Return [ mixed ]
}

In case you are using an older PHP version, it might not exist without loading a PHP extension:

$ php -n --rf json_decode
Exception: Function json_decode() does not exist

The JSON Text needs to be passed on the first parameter named json as a scalar type string value.

The resulting data can then be accessed on the functions return value.

My answer relates to this standard JSON text decoder in PHP, there are other decoders available which may yield different runtime behaviour which is not possible to cover in this answer. Nevertheless, sometimes I provide reference to other and related PHP extensions in this answer.

If a JSON text does not represent valid JSON for PHP, the json_validate() function returns false. Its properties are comparable to the decoding function, both for its availability and usage. Therefore I consider it part of the PHP JSON decoder (or PHP as a JSON parser) and specifically mention it as "valid JSON for PHP".

Given a JSON text, when it is provided as a string and valid JSON for PHP, then the decoding function will return the data in the PHP representation, a value with the union type of object|array|string|float|int|bool|null.

The data can then be stored in a variable by assigning the functions return value to it.

To make the decode function never returning on invalid JSON for PHP, the global constant JSON_THROW_ON_ERROR can be added to the flags scalar type integer value on the fourth parameter named flags.

Sections 4 and 8 of RFC8259 already identify specific situations that may conform to the grammar for JSON texts but are not interoperable uses of JSON, as they may cause unpredictable behavior.

JSON object properties are constrained by PHP, only a subset of JSON text can be decoded: A PHP object does not have same-named properties. The PHP JSON decoder will therefore create the JSON objects' member variable when decoded the first time and assign its value. The next time it will assign the value to the same member variable again, overwriting its previous value. This behaviour cannot be changed with a flag (fourth parameter of the decode function, see the first listing).

Another constraint is that not all JSON object property names are acceptable ones of PHP objects. If the JSON Text contains such property names that are not portable for PHP object member variable names, the second parameter of the decode function should be set to the scalar type boolean value true.

PHP then decodes all JSON objects as associative arrays which has wider compatibility as PHP array keys are less constrained than PHP object property (member variable) names.

This enhances the accessibility of the encoded JSON object members with the PHP JSON decoder but has the representation invariant that both empty arrays (lists) and empty objects (entities) collapse into the empty array and can't be distinguished from each other in the PHP representation any longer.

As long as no empty objects are expected or the decoding is done only to validate property names, this distinguishing may not be of concern, but this depends on how the return value of the PHP JSON decode function is being used.

The PHP JSON decoders' input string is binary (octets), and the only supported text encoding UTF-8 RFC3629. Previous specifications of JSON have not required the use of UTF-8 when transmitting JSON text. However, the JSON-based PHP implementation has chosen, as did many other JSON decoding libraries, to use the UTF-8 encoding, to the extent that it is the only encoding that achieves interoperability without relying on another PHP extension. The PHP JSON decoder treats the UTF-8 byte-order mark (BOM) as an error. This behaviour might be noteworthy and it cannot be changed with a flag.

Section 8.3 of RFC8259 identifies member names and string values that contain bit sequences that cannot encode Unicode characters; for example, "\uDEAD" (a single unpaired UTF-16 surrogate). Albeit the augmented Backus–Naur form (ABNF) of the JSON specification allows these member names, the behaviour of software that receives JSON text containing such values has already been identified as unpredictable (ebd.). The PHP JSON decoder yields these as JSON errors more predictably. As the PHP JSON decoder does not furthermore add constraints on names (and/or associated keys), this is both the baseline and the ceiling. The PHP JSON decoder has no further options, neither as a naming profile, schema validation or a reviver callback for the JSON decoding function.

Section 9 of RFC8259 describes a JSON parser. In hindsight of the PHP JSON decode function, it accepts all texts that conform to the JSON grammar and transforms it into another representation. The PHP representation is the returned value of the union type (see above) or by throwing a JsonException (ebd.). As a JSON parser may accept non-JSON forms or extensions, the PHP JSON decoder function does accept such texts, but they give a positive JSON error result as any other JSON text that is not considered valid JSON for PHP, folding to a null return value or throwing by the JSON_THROW_ON_ERROR flag in the error case.

JSON extensions like JSON5 are only available via other PHP extensions, for example SQLite —also via the PHP Data Objects (PDO).

The PHP JSON decoder sets limits on the size of texts that it accepts. This can be configured in PHP directives for the size of input variables and overall memory limit. Furthermore a PHP configuration is constrained at runtime by how much memory the operating system or SAPI host provides to the PHP process.

The PHP JSON decoder has a default limit on the maximum depth of nesting —512— which can be controlled by the third parameter named depth, a scalar type integer value —throws ValueError unless greater than 0.

Example 1. Decoding JSON Text Input in PHP

Decoding the JSON text of the question as PHP input with the PHP JSON decode function and accessing the data.

$data = json_decode(
    json       : file_get_contents('php://input'),
    associative: null,
    depth      : 4,
    flags      : JSON_THROW_ON_ERROR,
);

Each date in the data can be accessed by their names (variables) and keys (arrays/lists) within the potentially compound structure of the data interchanged via the JSON text in the decoded PHP representation of the data.

Names have a string representation in PHP and keys an integer, float or string representation.

For JSON arrays, the PHP decoder uses integer keys starting from zero until the count surpasses PHP_INT_MAX —a global constant type integer with the maximum positive integer value the PHP build is capable of—, then changing to float for the value of the key then implicitly converting to the integer type, an operation with precision-loss. This representation invariant is commonly ignored in PHP JSON decoding, because such arrays (as lists) are not fitting the short running request/response cycles during data-interchange for time and space. The size of such lists however cannot by limited with a parameter of the JSON decode function.

Consult the hosts PHP configuration for the value ranges of the numeric data types, as the PHP representation is accordingly for numeric values in the JSON text. The fourth parameter named flags of the PHP JSON decode function allows to control the behaviour of the parsing also in this regard, the JSON_BIGINT_AS_STRING flag directs the PHP JSON parser to decode large integers as their original string value —but not for array indexes. (ref.)

Names in their string representation can be made expressive by quoting the string literal in curly brackets ({…}). This is not a requirement thought as long as the identifier does not conflict with the PHP language internal syntax rules. Conflicts may arise on a reserved word of language and/or symbols of syntactic constructs, e.g. the curly brackets just mentioned or PHP token separating white-space sequences, PHP comment symbols, or sometimes even non-string literals. E.g., null is a valid name, 0 isn't. Expressing names by their string literals as in {'null'} and {'0'} unambiguously identifies them as names in the PHP language.

Variable names are prefixed with the dollar sign ($). Object variable names are prefixed with the hyphen-minus (-) immediately followed by the greater-than sign (>) forming a rightwards arrow → (->.)

Keys for both their integer and string representation are quoted in square brackets ([…]).

In the past, it was also possible to use curly brackets for array keys, that probably was useful for Perl linguists. This is now gone, enforcing more semantic clarity in the language.

As the two structured kinds of values, JSON object and JSON array, are decoded by the PHP JSON decode function into one of their two counter-parts, PHP object and PHP array, the data in the JSON text of the question can be accessed as a whole (variable) or as a subcomponent (array member/ object variable) finally reaching each date with the PHP expression naming —or pointing to— it.

Table 1. Accessing the Example Data decoded from JSON Text in PHP

Expression Date or Data
${'data'}->{'type'} 'donut'
${'data'}->{'name'} 'Cake'
${'data'}->{'toppings'}[0]->{'id'} '5002'
${'data'}->{'toppings'}[0]->{'type'} 'Glazed'
${'data'}->{'toppings'}[0] stdClass
${'data'}->{'toppings'}[1]->{'id'} '5006'
${'data'}->{'toppings'}[1]->{'type'} 'Chocolate with Sprinkles'
${'data'}->{'toppings'}[1] stdClass
${'data'}->{'toppings'}[2]->{'id'} '5004'
${'data'}->{'toppings'}[2]->{'type'} 'Maple'
${'data'}->{'toppings'}[2] stdClass
${'data'}->{'toppings'} array
${'data'} stdClass

And as previously outlined or per the Manual, or here.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.