Não é possível usar o objeto do tipo stdClass como matriz?

541

Eu recebo um erro estranho usando json_decode(). Ele decodificou corretamente os dados (eu o vi usando print_r), mas quando tento acessar as informações dentro da matriz, recebo:

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

Eu só tentei fazer: $result['context']onde $resultos dados retornados porjson_decode()

Como posso ler valores dentro dessa matriz?

Dail
fonte
15
$ result = json_decode ('a string', verdadeira); Adicionar true retorna o resultado como uma matriz e não como stdClass.
Nepaluz

Respostas:

790

Use o segundo parâmetro de json_decodepara fazê-lo retornar uma matriz:

$result = json_decode($data, true);
Jon
fonte
209

A função json_decode()retorna um objeto por padrão.

Você pode acessar os dados assim:

var_dump($result->context);

Se você tiver identificadores como from-date(o hífen causaria um erro de PHP ao usar o método acima), você deve escrever:

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

Se você deseja uma matriz, pode fazer algo assim:

$result = json_decode($json, true);

Ou converter o objeto em uma matriz:

$result = (array) json_decode($json);
svens
fonte
2
Levei um tempo para encontrar este ao tentar encontrar uma maneira de se referir ao valor _destroy em php que está definido por knockoutjs, então +1
deltree
2
Esta resposta é muito mais qualificada do que a primeira (a mais votada)!
Mojtaba Rezaeian
149

Você deve acessá-lo usando ->uma vez que é um objeto.

Mude seu código de:

$result['context'];

Para:

$result->context;
JiNexus
fonte
O problema que tenho é tentar usar a propriedade de forma condicional. if ($result->context = $var) Isso faz com que a propriedade seja definida como var e retorna true, não importa.
STWilson
3
@STWilson, você deve usar um duplo igual ==, no estado atual em que está atribuindo $varvalor $result->contextusando um único igual =. E o if statementlerá como se estivesse vazio ou não, e se $vartiver valor, isso significa que não está vazio e sempre retornará verdadeiro.
JiNexus
89

Tem o mesmo problema hoje, resolvido assim:

Se você ligar json_decode($somestring), receberá um Objeto e precisará acessar como $object->key, mas se você ligar json_decode($somestring, true), receberá um dicionário e poderá acessar como$array['key']

Alexey Lysenko
fonte
2
Isso me salvou tanto tempo! Eu não estava colocando no verdadeiro parâmetro, e tentando acessá-lo como uma matriz
Meeyam
87

Use truecomo o segundo parâmetro para json_decode. Isso decodificará o json em uma matriz associativa em vez de stdObjectinstâncias:

$my_array = json_decode($my_json, true);

Veja a documentação para mais detalhes.

Sander Marechal
fonte
61

Não é uma matriz, é um objeto do tipo stdClass.

Você pode acessá-lo assim:

echo $oResult->context;

Mais informações aqui: O que é stdClass no PHP?

Wesley van Opdorp
fonte
28

Como o Manual do Php diz,

print_r - Imprime informações legíveis por humanos sobre uma variável

Quando usamos json_decode();, obtemos um objeto do tipo stdClass como tipo de retorno. Os argumentos que devem ser passados ​​para dentro print_r()devem ser uma matriz ou uma string. Portanto, não podemos passar um objeto dentro de print_r(). Eu encontrei duas maneiras de lidar com isso.

  1. Lance o objeto para a matriz.
    Isso pode ser alcançado da seguinte maneira.

    $a = (array)$object;
  2. Acessando a chave do objeto
    Como mencionado anteriormente, quando você usa a json_decode();função, ele retorna um objeto de stdClass. você pode acessar os elementos do objeto com a ajuda do ->operador.

    $value = $object->key;

Um, também pode usar várias chaves para extrair os subelementos, caso o objeto tenha matrizes aninhadas.

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

print_r()Também existem outras opções , como var_dump();evar_export();

PS : Além disso, se você definir o segundo parâmetro de json_decode();para true, ele converterá automaticamente o objeto em um. array();
Aqui estão algumas referências:
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
fonte
12

Para obter uma matriz como resultado de uma string json, você deve definir o segundo parâmetro como boolean true.

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

Caso contrário, $ result será um objeto std. mas você pode acessar valores como objeto.

  $result = json_decode($json_string);
 $context = $result->context;
infomasud
fonte
8

Quando você tenta acessá-lo como $result['context'], você o trata como uma matriz, o erro está dizendo que você está realmente lidando com um objeto, então você deve acessá-lo como$result->context

Midas Mtileni
fonte
4

Aqui está a assinatura da função:

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

Quando param for false, que é o padrão, ele retornará um tipo de php apropriado. Você busca o valor desse tipo usando o paradigma object.method.

Quando param for verdadeiro, ele retornará matrizes associativas.

Ele retornará NULL por erro.

Se você deseja buscar valor através da matriz, defina assoc como true.

Robert
fonte
3

Às vezes, ao trabalhar com a API, você simplesmente deseja manter um objeto. Para acessar o objeto que contém objetos aninhados, você pode fazer o seguinte:

Assumiremos que quando você imprime o objeto, poderá ver o seguinte:

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
        )
)

Para acessar a primeira parte do objeto:

print $response->{'status'};

E isso produziria "sucesso"

Agora vamos digitar as outras partes:

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

A saída esperada seria "Robert" com uma quebra de linha.

Você também pode reatribuir parte do objeto a outro objeto.

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

A saída esperada seria "Robert" com uma quebra de linha.

Para acessar a próxima tecla "1", o processo é o mesmo.

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

A saída esperada seria "EUA"

Espero que isso ajude você a entender objetos e por que queremos manter um objeto. Você não precisa converter um objeto em uma matriz para acessar suas propriedades.

Robert Saylor
fonte
2

em vez de usar os colchetes, use o operador de objeto, por exemplo, minha matriz baseada no objeto de banco de dados é criada assim em uma classe chamada 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;
}

}

para acessar as informações, eu uso esse código no script do controlador:

<?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';



?>

para exibir as informações, verifico se as chamadas de serviço foram definidas e têm uma contagem maior que 0; lembre-se de que não é uma matriz que estou referenciando, para acessar os registros com o operador de objeto "->", assim:

<?php include $_SERVER['DOCUMENT_ROOT'] .'/includes/header.html.php';?>
<!--Main content-->
<div id="mainholder"> <!-- div so that page footer can have a minum 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="https://stackoverflow.com/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'; ?>
timmac15
fonte
2

Eu obtive esse erro do nada porque meu login no Facebook parou de funcionar de repente (eu também havia mudado de host) e lançou esse erro. A correção é realmente fácil

O problema estava neste código

  $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']);
  }

Basicamente, a função isset () espera uma matriz, mas encontra um objeto. A solução simples é converter o objeto PHP em array usando o quantificador (array) . O seguinte é o código fixo.

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

Observe o quantificador use off array () na primeira linha.

Hammad Khan
fonte
1

Mude para

$results->fetch_array()
Dan Padilla
fonte