Guzzle 6: no more json() method for responses
Solution 1:
I use json_decode($response->getBody())
now instead of $response->json()
.
I suspect this might be a casualty of PSR-7 compliance.
Solution 2:
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.
Solution 3:
I use $response->getBody()->getContents()
to get JSON from response.
Guzzle version 6.3.0.
Solution 4:
If you guys still interested, here is my workaround based on Guzzle middleware feature:
-
Create
JsonAwaraResponse
that will decode JSON response byContent-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; } }
-
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
Solution 5:
$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
-
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. - Don't use
$response->getBody()->getContents()
unless you know what you're doing. If you read documentation forgetContents()
, it says:Returns the remaining contents in a string
. Therefore, callinggetContents()
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.