Guzzle 6: no more json() method for responses

前端 未结 6 1508
悲哀的现实
悲哀的现实 2020-12-02 08:17

Previously in Guzzle 5.3:

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


        
相关标签:
6条回答
  • 2020-12-02 08:33

    You switch to:

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

    Instead of the other comment if you want it to work exactly as before in order to get arrays instead of objects.

    0 讨论(0)
  • 2020-12-02 08:43

    I use json_decode($response->getBody()) now instead of $response->json().

    I suspect this might be a casualty of PSR-7 compliance.

    0 讨论(0)
  • 2020-12-02 08:43

    Adding ->getContents() doesn't return jSON response, instead it returns as text.

    You can simply use json_decode

    0 讨论(0)
  • 2020-12-02 08:51

    If you guys still interested, here is my workaround based on Guzzle middleware feature:

    1. Create JsonAwaraResponse that will decode JSON response by Content-Type HTTP header, if not - it will act as standard Guzzle Response:

      <?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. Create Middleware which going to replace Guzzle PSR-7 responses with above Response implementation:

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

    After this to retrieve JSON as PHP native array use Guzzle as always:

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

    Tested with guzzlehttp/guzzle 6.3.3

    0 讨论(0)
  • 2020-12-02 08:52

    $response is instance of PSR-7 ResponseInterface. For more details see https://www.php-fig.org/psr/psr-7/#3-interfaces

    getBody() returns StreamInterface:

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

    StreamInterface implements __toString() which does

    Reads all data from the stream into a string, from the beginning to end.

    Therefore, to read body as string, you have to cast it to string:

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


    Gotchas

    1. json_decode($response->getBody() is not the best solution as it magically casts stream into string for you. json_decode() requires string as 1st argument.
    2. Don't use $response->getBody()->getContents() unless you know what you're doing. If you read documentation for getContents(), it says: Returns the remaining contents in a string. Therefore, calling getContents() reads the rest of the stream and calling it again returns nothing because stream is already at the end. You'd have to rewind the stream between those calls.
    0 讨论(0)
  • 2020-12-02 08:55

    I use $response->getBody()->getContents() to get JSON from response. Guzzle version 6.3.0.

    0 讨论(0)
提交回复
热议问题