Guzzle 6:没有更多的json()方法用于响应

rap*_*2-h 153 php guzzle

以前在Guzzle 5.3中:

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

我可以轻松地从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']);
Run Code Online (Sandbox Code Playgroud)

还是有帮手或类似的东西?

mer*_*ial 262

json_decode($response->getBody())现在用而不是$response->json().

我怀疑这可能是PSR-7合规性的牺牲品.

  • 如果您期望像原始` - > json()`一样工作的数组响应,请使用`json_decode($ response-> getBody(),true)`来获取数组而不是stdObject (54认同)
  • 使用`strict_types`,我需要在解码之前将Guzzle响应体强制转换为字符串:`json_decode((string)$ response-> getBody(),true)` (9认同)
  • 在文档中没有任何内容使这个显而易见,但确实看起来他们已经淘汰了`$ response-> json()`帮助器. (4认同)
  • 我总是喜欢使用 `\GuzzleHttp\json_decode` (或 `\GuzzleHttp\Utils::jsonDecode` ,具体取决于您所使用的 Guzzle 版本),它具有与 `\json_decode` 兼容的签名,但如果存在则抛出异常错误,利用正确的错误处理。 (2认同)

dmy*_*ers 104

你切换到:

json_decode($response->getBody(), true)
Run Code Online (Sandbox Code Playgroud)

而不是其他注释,如果你想让它像以前一样工作,以获得数组而不是对象.


小智 24

我用来$response->getBody()->getContents()从响应中获取JSON.Guzzle版本6.3.0.

  • 在响应主体中调用`getContents()`将清空流,而对`getContents()`的下一次调用将返回空。如果要以字符串形式获取正文,请使用:`strval($ response-> getBody())` (4认同)
  • 我希望这个评论更高。我正在使用 getContent 记录我的响应,当我稍后解析一行时,我的数组是空的。花了我几个小时。谢谢! (2认同)

小智 11

如果你们仍然感兴趣,这是我基于Guzzle 中间件功能的解决方法:

  1. 创建JsonAwaraResponse将通过Content-TypeHTTP标头解码JSON响应的代码,如果没有,则将作为标准的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;
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 创建中间件,该中间件将用上面的Response实现替换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');
    
    Run Code Online (Sandbox Code Playgroud)

之后,将JSON作为PHP本机数组来检索,请像往常一样使用Guzzle:

$jsonArray = $client->get('http://httpbin.org/headers')->getBody();
Run Code Online (Sandbox Code Playgroud)

用guzzlehttp / guzzle 6.3.3测试

  • @SergeyNevmerzhitsky 提到的问题的一个潜在解决方案可能是将 JsonAwareResponse 转换为装饰器,然后实现 `__call()` 将调用转发到实际响应。然后你可以添加一个 `getJson()` 或任何你想要的。 (4认同)

sim*_*Pod 8

$response是 PSR-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();
Run Code Online (Sandbox Code Playgroud)

StreamInterface实现__toString()

将流中的所有数据从头到尾读取到字符串中。

因此,要将正文读取为字符串,您必须将其转换为字符串:

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


陷阱

  1. json_decode($response->getBody()不是最好的解决方案,因为它神奇地为您将流转换为字符串。json_decode()需要字符串作为第一个参数。
  2. $response->getBody()->getContents()除非您知道自己在做什么,否则请勿使用。如果您阅读 的文档getContents(),它会说:Returns the remaining contents in a string。因此,调用会getContents()读取流的其余部分,并再次调用它不会返回任何内容,因为流已经位于末尾。您必须在这些调用之间倒带流。