703

I get a strange error using json_decode(). It decodes the data correctly (I saw it using print_r), but when I try to access to information inside the array I get:

Fatal error: Cannot use object of type stdClass as array in
C:\Users\Dail\software\abs.php on line 108

I only tried to do: $result['context'] where $result has the data returned by json_decode()

How can I read values inside this array?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Dail
  • 7,039
  • 3
  • 15
  • 3

17 Answers17

1047

Use the second parameter of json_decode to make it return an array:

$result = json_decode($data, true);
Jon
  • 428,835
  • 81
  • 738
  • 806
270

The function json_decode() returns an object by default.

You can access the data like this:

var_dump($result->context);

If you have identifiers like from-date (the hyphen would cause a PHP error when using the above method) you have to write:

var_dump($result->{'from-date'});

If you want an array you can do something like this:

$result = json_decode($json, true);

Or cast the object to an array:

$result = (array) json_decode($json);
svens
  • 11,438
  • 6
  • 36
  • 55
204

You must access it using -> since it’s an object.

Change your code from:

$result['context'];

To:

$result->context;
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
JiNexus
  • 2,754
  • 1
  • 19
  • 17
  • The problem I have is trying to use the property in a conditional `if ($result->context = $var)` This causes the property to be set to the var and returns true, no matter. – STWilson Nov 16 '16 at 21:28
  • 4
    @STWilson you should be using a double equals `==`, in your current state you are assigning `$var` value to `$result->context` by using a single equal `=`. And the `if statement` will read it as if it is empty or not, and if the `$var` has value then that means it is not empty and will always return true. – JiNexus Nov 16 '16 at 23:26
  • Why does this page seem to indicate that both syntaxes are allowed: https://www.php.net/manual/en/sdo.sample.getset.php – kojow7 Jan 08 '21 at 03:37
  • @kojow7 If you are referring to this `$company->departments[0]->name` it is because it is directly accessing the object using an array index. The structure of the data is that, objects are stored in array. – JiNexus Feb 03 '21 at 22:40
  • @JiNexus I mean examples #1 and #2 on that page. Example #1 says you can use: `$company->name = 'Acme';` and Example #2 says you can use: `$company['name'] = 'UltraCorp';` – kojow7 Feb 04 '21 at 00:13
  • @kojow7 you can use them in assignment but go back to the main question of this thread he is asking how to access it. So depending of the data type that's how you access both array and object. – JiNexus Feb 04 '21 at 02:46
  • @JNexus If you look at example #2 on the page it shows examples of accessing it on the left hand and right hand side of the assignment operator. Therefore, it is showing that it can be both used in assignment and retrieving data from it. – kojow7 Feb 04 '21 at 05:59
111

Use true as the second parameter to json_decode. This will decode the JSON content into an associative array instead of stdObject instances:

$my_array = json_decode($my_json, true);

See the documentation for more details.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Sander Marechal
  • 22,978
  • 13
  • 65
  • 96
98

I have the same problem today and solved like this:

If you call json_decode($somestring), you will get an Object and you need to access like $object->key, but if you call json_decode($somestring, true) you will get a dictionary and can access like $array['key'].

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Alexey Lysenko
  • 1,890
  • 2
  • 12
  • 28
  • 2
    This saved me sooo much time! I was not putting in the true parameter, and trying to access it as an array – Meeyam Dec 07 '18 at 23:07
  • Life saver! Especially with `echo json_decode('{"Contains Space":999}', true)['Contains Space'] . "\n";` – Neil Gatenby Nov 23 '20 at 09:41
71

It's not an array; it's an object of type stdClass.

You can access it like this:

echo $oResult->context;

More information is in What is stdClass in PHP?.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Wesley van Opdorp
  • 14,888
  • 4
  • 41
  • 59
31

As the Php Manual say,

print_r — Prints human-readable information about a variable

When we use json_decode();, we get an object of type stdClass as return type. The arguments, which are to be passed inside of print_r() should either be an array or a string. Hence, we cannot pass an object inside of print_r(). I found 2 ways to deal with this.

  1. Cast the object to array.
    This can be achieved as follows.

    $a = (array)$object;
    
  2. By accessing the key of the Object
    As mentioned earlier, when you use json_decode(); function, it returns an Object of stdClass. you can access the elements of the object with the help of -> Operator.

    $value = $object->key;
    

One, can also use multiple keys to extract the sub elements incase if the object has nested arrays.

$value = $object->key1->key2->key3...;

Their are other options to print_r() as well, like var_dump(); and var_export();

P.S : Also, If you set the second parameter of the json_decode(); to true, it will automatically convert the object to an array();
Here are some references:
http://php.net/manual/en/function.print-r.php
http://php.net/manual/en/function.var-dump.php
http://php.net/manual/en/function.var-export.php

Panda
  • 2,400
  • 3
  • 25
  • 35
28

Try something like this one!

Instead of getting the context like (this works for getting array index's),

$result['context']

try (this work for getting objects):

$result->context

Another example is (if $result has multiple data values):

Array
(
    [0] => stdClass Object
        (
            [id] => 15
            [name] => 1 Pc Meal
            [context] => 5
            [restaurant_id] => 2
            [items] =>
            [details] => 1 Thigh (or 2 Drums) along with Taters
            [nutrition_fact] => {"":""}
            [servings] => menu
            [availability] => 1
            [has_discount] => {"menu":0}
            [price] => {"menu":"8.03"}
            [discounted_price] => {"menu":""}
            [thumbnail] => YPenWSkFZm2BrJT4637o.jpg
            [slug] => 1-pc-meal
            [created_at] => 1612290600
            [updated_at] => 1612463400
        )

)

Then try this:

foreach($result as $results)
{
    $results->context;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
codelone
  • 604
  • 8
  • 17
25

To get an array as result from a json string you should set second param as boolean true.

$result = json_decode($json_string, true);
$context = $result['context'];

Otherwise $result will be an std object. but you can access values as object.

  $result = json_decode($json_string);
 $context = $result->context;
infomasud
  • 2,263
  • 1
  • 18
  • 12
20

Sometimes when working with API you simply want to keep an object an object. To access the object that has nested objects you could do the following:

We will assume when you print_r the object you might see this:

print_r($response);

stdClass object
(
    [status] => success
    [message] => Some message from the data
    [0] => stdClass object
        (
            [first] => Robert
            [last] => Saylor
            [title] => Symfony Developer
        )
    [1] => stdClass object
        (
            [country] => USA
        )
)

To access the first part of the object:

print $response->{'status'};

And that would output "success"

Now let's key the other parts:

$first = $response->{0}->{'first'};
print "First name: {$first}<br>";

The expected output would be "Robert" with a line break.

You can also re-assign part of the object to another object.

$contact = $response->{0};
print "First Name: " . $contact->{'first'} . "<br>";

The expected output would be "Robert" with a line break.

To access the next key "1" the process is the same.

print "Country: " . $response->{1}->{'country'} . "<br>";

The expected output would be "USA"

Hopefully this will help you understand objects and why we want to keep an object an object. You should not need to convert an object to an array to access its properties.

Robert Saylor
  • 1,279
  • 9
  • 11
9

You can convert the stdClass object to an array like:

$array = (array)$stdClass;

stdClsss to array

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Arnab
  • 4,216
  • 2
  • 28
  • 50
8

When you try to access it as $result['context'], you treating it as an array, the error it's telling you that you are actually dealing with an object, then you should access it as $result->context

Tom
  • 4,257
  • 6
  • 33
  • 49
Midas Mtileni
  • 91
  • 1
  • 4
4

Here is the function signature:

mixed json_decode ( string $json [, bool $assoc = false [, int $depth = 512 [, int $options = 0 ]]] )

When a parameter is false, which is the default, it will return an appropriate PHP type. You fetch the value of that type using object.method paradigm.

When a parameter is true, it will return associative arrays.

It will return NULL on error.

If you want to fetch a value through an array, set assoc to true.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
robert
  • 598
  • 1
  • 5
  • 12
2

I got this error out of the blue because my facebook login suddently stopped working (I had also changed hosts) and throwed this error. The fix is really easy

The issue was in this code

  $response = (new FacebookRequest(
    FacebookSession::newAppSession($this->appId, $this->appSecret),
    'GET',
    '/oauth/access_token',
    $params
  ))->execute()->getResponse(true);

  if (isset($response['access_token'])) {       <---- this line gave error
    return new FacebookSession($response['access_token']);
  }

Basically isset() function expect an array but instead it find an object. The simple solution is to convert PHP object to array using (array) quantifier. The following is the fixed code.

  $response = (array) (new FacebookRequest(
    FacebookSession::newAppSession($this->appId, $this->appSecret),
    'GET',
    '/oauth/access_token',
    $params
  ))->execute()->getResponse(true);

Note the use off array() quantifier in first line.

TheTechGuy
  • 16,560
  • 16
  • 115
  • 136
1

Instead of using the brackets, use the object operator. For example, my array based on a database object is created like this in a class called DB:

class DB {

    private static $_instance = null;

    private $_pdo,
            $_query,
            $_error = false,
            $_results,
            $_count = 0;

    private function __construct() {
        try {
            $this->_pdo = new PDO('mysql:host=' . Config::get('mysql/host') . ';dbname=' . Config::get('mysql/db'), Config::get('mysql/username'), Config::get('mysql/password'));
        }
        catch(PDOException $e) {
            $this->_error = true;
            $newsMessage = 'Sorry.  Database is off line';
            $pagetitle = 'Teknikal Tim - Database Error';
            $pagedescription = 'Teknikal Tim Database Error page';
            include_once 'dbdown.html.php';
            exit;
        }
        $headerinc = 'header.html.php';
    }

    public static function getInstance() {
        if(!isset(self::$_instance)) {
            self::$_instance = new DB();
        }
        return self::$_instance;
    }

    public function query($sql, $params = array()) {
        $this->_error = false;
        if($this->_query = $this->_pdo->prepare($sql)) {
            $x = 1;
            if(count($params)) {
                foreach($params as $param) {
                    $this->_query->bindValue($x, $param);
                    $x++;
                }
            }
        }

        if($this->_query->execute()) {

            $this->_results = $this->_query->fetchAll(PDO::FETCH_OBJ);
            $this->_count = $this->_query->rowCount();
        }
        else {
            $this->_error = true;
        }

        return $this;
    }

    public function action($action, $table, $where = array()) {
        if(count($where) === 3) {
            $operators = array('=', '>', '<', '>=', '<=');

            $field    = $where[0];
            $operator = $where[1];
            $value    = $where[2];

            if(in_array($operator, $operators)) {
                $sql = "{$action} FROM {$table} WHERE {$field} = ?";

                if(!$this->query($sql, array($value))->error()) {
                    return $this;
                }
            }
        }
        return false;
    }

    public function get($table, $where) {
        return $this->action('SELECT *', $table, $where);

    public function results() {
        return $this->_results;
    }

    public function first() {
        return $this->_results[0];
    }

    public function count() {
        return $this->_count;
    }

}

To access the information, I use this code on the controller script:

<?php
    $pagetitle = 'Teknikal Tim - Service Call Reservation';
    $pagedescription = 'Teknikal Tim Sevice Call Reservation Page';
    require_once $_SERVER['DOCUMENT_ROOT'] . '/core/init.php';
    $newsMessage = 'temp message';

    $servicecallsdb = DB::getInstance()->get('tt_service_calls', array('UserID', '=', '$_SESSION['UserID']));

    if(!$servicecallsdb) {
        //$servicecalls[] = array('ID'=>'', 'ServiceCallDescription'=>'No Service Calls');
    } else {
        $servicecalls = $servicecallsdb->results();
    }
    include 'servicecalls.html.php';
?>

Then to display the information. I check to see if servicecalls has been set and has a count greater than 0. Remember it's not an array I am referencing, so I access the records with the object operator "->" like this:

<?php include $_SERVER['DOCUMENT_ROOT'] . '/includes/header.html.php';?>

<!-- Main content -->
<div id="mainholder"> <!-- div so that page footer can have a minimum
                           height from the header -->
<h1><?php if(isset($pagetitle)) htmlout($pagetitle);?></h1>
<br>
<br>
<article>
    <h2></h2>
</article>

<?php
    if (isset($servicecalls)) {
        if (count ($servicecalls) > 0) {
             foreach ($servicecalls as $servicecall) {
                echo '<a href="/servicecalls/?servicecall=' .
                     $servicecall->ID . '">' .
                     $servicecall->ServiceCallDescription .'</a>';
            }
        }
        else
            echo 'No service Calls';
    }
?>

<a href="/servicecalls/?new=true">Raise New Service Call</a>
</div> <!-- Main content end -->

<?php include $_SERVER['DOCUMENT_ROOT'] . '/includes/footer.html.php'; ?>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
timmac15
  • 59
  • 3
0

It is most likely when it tries to access the data with the generic bracket array accessor and not an object operator. Always ensure the variable type is before accessing the data.

While decoding the JSON, the response will be generated as stdObject instances

Rather than calling $result['context'];, access it by $result->context;

If it needs to call as an array itself, decode the JSON by passing the second parameter as true like

json_decode($jsonData, true);
Nishal K.R
  • 1,090
  • 11
  • 21
-1

Change it for

$results->fetch_array()