Guzzle 6: Yanıtlar için artık json () yöntemi yok


172

Daha önce Guzzle 5.3'te:

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

Kolayca bir JSON yanıtı bir PHP dizi alabilir. Şimdi Guzzle 6'da nasıl yapılacağını bilmiyorum. json()Artık bir yöntem yok gibi görünüyor . Dokümanı en son sürümden (hızlı bir şekilde) okudum ve JSON yanıtları hakkında hiçbir şey bulamadım. Sanırım bir şeyi kaçırdım, belki anlamadığım yeni bir kavram var (ya da belki de doğru okumadım).

Bu (aşağıda) yeni yol tek yol mu?

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

Yoksa bir yardımcı ya da bunun gibi bir şey var mı?

Yanıtlar:


292

json_decode($response->getBody())Şimdi yerine kullanıyorum $response->json().

Bunun PSR-7 uyumluluğunda bir kayıp olabileceğinden şüpheleniyorum.


4
Belgelerde bunu açıkça belirten hiçbir şey yok, ancak $response->json()yardımcıyı aşamalı olarak kaldırmışlar gibi görünüyor .
ataç

60
Orijinalin nasıl ->json()çalıştığı gibi bir dizi yanıtı bekliyorsanız , json_decode($response->getBody(), true)bunun yerine stdObject yerine bir dizi almak için kullanın
Jay El-Kaake 23:15

14
Kullanarak strict_types, kod json_decode((string) $response->getBody(), true)
çözmeden

Her zaman uyumlu bir imzası olan \GuzzleHttp\json_decode(veya \GuzzleHttp\Utils::jsonDecodeüzerinde olduğunuz Guzzle sürümüne bağlı olarak) kullanmayı sevdim \json_decode, ancak bir hata varsa bir istisna atar, uygun hata işleme özelliğini kullanır.
Adrian Föder

112

Şuna geçersiniz:

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

Diğer yorum yerine nesneler yerine diziler almak için daha önce olduğu gibi çalışmasını istiyorsanız.


29

$response->getBody()->getContents()Yanıttan JSON almak için kullanıyorum . Guzzle sürüm 6.3.0.


6
Arayan getContents()tepki vücutta akışını ve sonraki çağrısı boşaltacaktır getContents()boş dönecektir. Vücudu dize olarak kullanmak istiyorsanız:strval($response->getBody())
JVitela

1
Keşke bu yorum daha yüksek olsaydı. GetContent kullanarak yanıtımı günlüğe kaydediyordum ve bir satırı daha sonra ayrıştırmaya gittiğimde, dizim boştu. Bana saatlerce mal oldu. Teşekkürler!
Colin

14

Hala ilgileniyorsanız, işte Guzzle ara katman yazılımı özelliğine dayalı geçici çözüm :

  1. JsonAwaraResponseJSON yanıtının Content-TypeHTTP üstbilgisiyle kodunu çözecek şekilde oluşturun , değilse - standart Guzzle Yanıtı olarak işlev görür:

    <?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. Guzzle PSR-7 yanıtlarını yukarıdaki Yanıt uygulamasıyla değiştirecek Middleware oluşturun :

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

Bundan sonra PHP yerel dizisi olarak JSON almak için her zaman olduğu gibi Guzzle kullanın:

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

Guzzlehttp / guzzle ile test edildi 6.3.3


Bu iyi şeyler. Ben sadece iş yerinde aldı bir Rest API İstemci görevi kullanarak. Yine de cevabınızla ilgili bir sorum var. JsonAwareResponse sınıfınızın GuzzleHttp ad alanı altında olması amaçlandı mı? Ben sadece kendi isim alanım altında bu sınıfı yarattım, ama bir saniye için GuzzleHttp kod tabanı etrafında bu sınıfı arıyor. :) Tekrar teşekkürler!
floorz

Bu çözümü kullanmayın çünkü PSR-7 arayüzünü bozar MessageInterface. PSR-7 ile kodu çözülmüş JSON'u getBody()yöntemden döndürmek için bu arabirimi düzeltmek için yasal bir çözüm yoktur .
Sergey Nevmerzhitsky

3

$responsePSR-7 örneğidir ResponseInterface. Daha fazla ayrıntı için bkz. Https://www.php-fig.org/psr/psr-7/#3-interfaces

getBody()döner StreamInterface:

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

StreamInterface__toString()hangi uygular

Akıştaki tüm verileri baştan sona bir dizeye okur.

Bu nedenle, gövdeyi dize olarak okumak için dizeye yayınlamanız gerekir:

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


Sorunlar

  1. json_decode($response->getBody()sihirli bir şekilde sizin için dize içine yayınlar gibi en iyi çözüm değildir. json_decode()1. argüman olarak dize gerektirir.
  2. Ne $response->getBody()->getContents()yaptığınızı bilmiyorsanız kullanmayın . Eğer belgeleri için okursanız getContents(), diyor: Returns the remaining contents in a string. Bu nedenle, çağırma getContents()akışın geri kalanını okur ve akış zaten sonunda olduğu için tekrar çağırmak hiçbir şey döndürmez. Bu aramalar arasındaki akışı geri sarmanız gerekir.

1

Ekleme ->getContents()jSON yanıtı döndürmez, metin olarak döndürür.

Sadece kullanabilirsiniz json_decode


JSON'u HTML olarak değil metin olarak döndürür.
František Maša
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.