Guzzle 6: niente più metodo json () per le risposte


172

Precedentemente in Guzzle 5.3:

$response = $client->get('http://httpbin.org/get');
$array = $response->json(); // Yoohoo
var_dump($array[0]['origin']);

Potrei facilmente ottenere un array PHP da una risposta JSON. Ora in Guzzle 6, non so come fare. Sembra che non ci sia più alcun json()metodo. Ho (rapidamente) letto il documento dall'ultima versione e non ho trovato nulla sulle risposte JSON. Penso di essermi perso qualcosa, forse c'è un nuovo concetto che non capisco (o forse non ho letto correttamente).

Questo (sotto) nuovo modo è l'unico modo?

$response = $client->get('http://httpbin.org/get');
$array = json_decode($response->getBody()->getContents(), true); // :'(
var_dump($array[0]['origin']);

O c'è un aiutante o qualcosa del genere?

Risposte:


292

Io uso json_decode($response->getBody())ora invece di $response->json().

Ho il sospetto che questa potrebbe essere una vittima della conformità PSR-7.


4
Nulla nella documentazione che lo rende esplicito, ma sembra che abbiano eliminato gradualmente l' $response->json()aiutante.
graffetta

60
Se ti aspetti una risposta da array come il ->json()funzionamento dell'originale , utilizza json_decode($response->getBody(), true)invece per ottenere un array anziché uno stdObject
Jay El-Kaake,

14
Usando strict_types, avevo bisogno di lanciare il corpo della risposta Guzzle su una stringa prima di decodificarlo:json_decode((string) $response->getBody(), true)
Yoan Tournade,

Mi è sempre piaciuto usare \GuzzleHttp\json_decode(o in \GuzzleHttp\Utils::jsonDecodebase alla versione di Guzzle in cui ti trovi) che ha una firma compatibile \json_decode, ma genera un'eccezione in caso di errore, sfruttando la corretta gestione degli errori.
Adrian Föder,

112

Passa a:

json_decode($response->getBody(), true)

Invece dell'altro commento, se vuoi che funzioni esattamente come prima per ottenere array invece di oggetti.


29

Uso $response->getBody()->getContents()per ottenere JSON dalla risposta. Versione Guzzle 6.3.0.


6
La chiamata getContents()nel corpo della risposta svuoterà lo stream e la chiamata successiva a getContents()tornerà vuota. Se si desidera ottenere il corpo come stringa utilizzare:strval($response->getBody())
JVitela

1
Vorrei che questo commento fosse più alto. Stavo registrando la mia risposta usando getContent e quando sono andato ad analizzare una riga in seguito, il mio array era vuoto. Mi è costato ore. Grazie!
Colin,

14

Se siete ancora interessati, ecco la mia soluzione alternativa basata sulla funzione middleware Guzzle :

  1. Crea JsonAwaraResponseche decodificherà la risposta JSON tramite l' Content-Typeintestazione HTTP, in caso contrario - fungerà da risposta standard Guzzle:

    <?php
    
    namespace GuzzleHttp\Psr7;
    
    
    class JsonAwareResponse extends Response
    {
        /**
         * Cache for performance
         * @var array
         */
        private $json;
    
        public function getBody()
        {
            if ($this->json) {
                return $this->json;
            }
            // get parent Body stream
            $body = parent::getBody();
    
            // if JSON HTTP header detected - then decode
            if (false !== strpos($this->getHeaderLine('Content-Type'), 'application/json')) {
                return $this->json = \json_decode($body, true);
            }
            return $body;
        }
    }
  2. Crea un middleware che sostituirà le risposte di Guzzle PSR-7 con l'implementazione della risposta sopra:

    <?php
    
    $client = new \GuzzleHttp\Client();
    
    /** @var HandlerStack $handler */
    $handler = $client->getConfig('handler');
    $handler->push(\GuzzleHttp\Middleware::mapResponse(function (\Psr\Http\Message\ResponseInterface $response) {
        return new \GuzzleHttp\Psr7\JsonAwareResponse(
            $response->getStatusCode(),
            $response->getHeaders(),
            $response->getBody(),
            $response->getProtocolVersion(),
            $response->getReasonPhrase()
        );
    }), 'json_decode_middleware');

Dopodiché, per recuperare JSON come array nativo PHP, utilizzare Guzzle come sempre:

$jsonArray = $client->get('http://httpbin.org/headers')->getBody();

Testato con guzzlehttp / guzzle 6.3.3


Questa è roba buona. Uso in un'attività client API Rest che ho appena raccolto al lavoro. Ho una domanda sulla tua risposta però. La tua classe JsonAwareResponse doveva essere nello spazio dei nomi GuzzleHttp? Ho finito per creare quella classe nel mio spazio dei nomi, ma per un secondo stavo cercando nella base di codice di GuzzleHttp cercando quella classe. :) Grazie ancora!
floorz,

Non utilizzare questa soluzione perché interrompe l'interfaccia PSR-7 MessageInterface. Con PSR-7 non esiste una soluzione legale per correggere questa interfaccia per restituire JSON decodificato dal getBody()metodo.
Sergey Nevmerzhitsky,

3

$responseè un'istanza di PSR-7 ResponseInterface. Per maggiori dettagli vedi https://www.php-fig.org/psr/psr-7/#3-interfaces

getBody()ritorna StreamInterface:

/**
 * Gets the body of the message.
 *
 * @return StreamInterface Returns the body as a stream.
 */
public function getBody();

StreamInterfacestrumenti __toString()che lo fanno

Legge tutti i dati dallo stream in una stringa, dall'inizio alla fine.

Pertanto, per leggere il corpo come stringa, devi lanciarlo su stringa:

$stringBody = (string) $response->getBody()


Trabocchetti

  1. json_decode($response->getBody()non è la soluzione migliore in quanto lancia magicamente stream in string per te. json_decode()richiede la stringa come primo argomento.
  2. Non usare $response->getBody()->getContents()se non sai cosa stai facendo. Se si legge la documentazione per getContents(), si dice: Returns the remaining contents in a string. Pertanto, la chiamata getContents()legge il resto dello stream e la sua chiamata di nuovo non restituisce nulla perché lo stream è già alla fine. Dovresti riavvolgere il flusso tra quelle chiamate.

1

L'aggiunta ->getContents()non restituisce risposta jSON, ma restituisce come testo.

Puoi semplicemente usare json_decode


Restituisce JSON come testo, non HTML.
František Maša,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.