Guzzle 6:応答用のjson()メソッドはもうありません


172

以前はGuzzle 5.3で:

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

JSON応答から簡単にPHP配列を取得できました。現在、Guzzle 6では、方法がわかりません。何もないように思わjson()もう方法。私は(迅速に)最新バージョンのドキュメントを読みましたが、JSON応答について何も見つかりませんでした。私は何かを逃したと思います、多分私は理解していない(または多分私は正しく読んでいない)新しい概念があるでしょう。

これが(下の)新しい方法だけですか?

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

またはヘルパーまたはそのようなものはありますか?

回答:


292

json_decode($response->getBody())代わりに今使ってい$response->json()ます。

これはPSR-7準拠の犠牲になるのではないかと思います。


4
これを明示するドキュメントには何もありませんが、$response->json()ヘルパーが段階的に廃止されているようです。
クリップ

60
オリジナルがどのように機能するかのような配列応答を期待している場合->json()は、json_decode($response->getBody(), true)代わりにstdObjectの代わりに配列を取得するために使用してください
Jay El-

14
を使用してstrict_types、デコードする前にGuzzleレスポンスボディを文字列にキャストする必要がありました:json_decode((string) $response->getBody(), true)
Yoan Tournade

112

次のように切り替えます。

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

オブジェクトの代わりに配列を取得するために以前とまったく同じように動作させたい場合は、他のコメントの代わりに。


29

$response->getBody()->getContents()応答からJSONを取得するために使用します。Guzzleバージョン6.3.0。


6
getContents()応答本文で呼び出すと、ストリームが空になり、への次の呼び出しでgetContents()は空が返されます。ボディを文字列として取得する場合:strval($response->getBody())
JVitela

1
このコメントがもっと高かったらいいのに。getContentを使用して応答をログに記録していて、後で行を解析するときに、配列が空でした。何時間もかかった。ありがとう!
コリン

14

まだ興味がある場合は、Guzzle ミドルウェア機能に基づく私の回避策を次に示します。

  1. HTTPヘッダーJsonAwaraResponseによってJSON応答をデコードするものを作成しますContent-Type(そうでない場合)-標準の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. Guzzle PSR-7応答を上記の応答実装に置き換えるミドルウェアを作成します。

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

この後、JSONをPHPネイティブ配列として取得するには、いつものようにGuzzleを使用します。

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

guzzlehttp / guzzle 6.3.3でテスト済み


これは良いものです。仕事で拾ったRest APIクライアントタスクでの使用。私はあなたの答えについて一つ質問があります。JsonAwareResponseクラスはGuzzleHttp名前空間の下にあることを意図していたのですか?私は自分の名前空間の下にそのクラスを作成するだけになりましたが、しばらくの間、GuzzleHttpのコードベースを探してそのクラスを探していました。:) 再度、感謝します!
floorz

このソリューションはPSR-7インターフェイスを破壊するため、使用しないでくださいMessageInterface。PSR-7では、getBody()メソッドからデコードされたJSONを返すようにこのインターフェイスにパッチを適用するための法的な解決策はありません。
Sergey Nevmerzhitsky

3

$responsePSR-7のインスタンスですResponseInterface。詳細については、https://www.php-fig.org/psr/psr-7/#3-interfacesを参照してください

getBody()を返しますStreamInterface

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

StreamInterface実装__toString()

最初から最後まで、ストリームからすべてのデータを文字列に読み取ります。

したがって、本文を文字列として読み取るには、それを文字列にキャストする必要があります。

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


ガチャ

  1. json_decode($response->getBody()ストリームを魔法のように文字列にキャストするため、最適なソリューションではありません。json_decode()最初の引数として文字列が必要です。
  2. $response->getBody()->getContents()何をしているかわからない場合は使用しないでください。のドキュメントを読むとgetContents()、次のようになりますReturns the remaining contents in a string。したがって、呼び出しgetContents()は残りのストリームを読み取り、ストリームを既に呼び出しているため、再度呼び出しても何も返されません。これらの呼び出しの間でストリームを巻き戻す必要があります。

1

追加->getContents()してもjSON応答は返されず、代わりにテキストとして返されます。

あなたは簡単に使うことができます json_decode


HTMLではなく、テキストとしてJSONを返します。
FrantišekMASA
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.