php Guzzle 6:不再有响应的 json() 方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30530172/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 21:51:11  来源:igfitidea点击:

Guzzle 6: no more json() method for responses

phpguzzle

提问by rap-2-h

Previously in Guzzle 5.3:

之前在 Guzzle 5.3 中:

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

I could easily get a PHP array from a JSON response. Now In Guzzle 6, I don't know how to do. There seems to be no json()method anymore. I (quickly) read the doc from the latest version and don't found anything about JSON responses. I think I missed something, maybe there is a new concept that I don't understand (or maybe I did not read correctly).

我可以轻松地从 JSON 响应中获取 PHP 数组。现在在 Guzzle 6 中,我不知道该怎么做。好像没有json()办法了。我(快速)阅读了最新版本的文档,但没有找到任何关于 JSON 响应的信息。我想我错过了一些东西,也许有一个我不理解的新概念(或者我没有正确阅读)。

Is this (below) new way the only way?

这是(下面)新方法的唯一方法吗?

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

Or is there an helper or something like that?

或者有没有帮手之类的?

回答by meriial

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

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

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

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

回答by dmyers

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.

如果您希望它像以前一样工作以获取数组而不是对象,则不要使用其他注释。

回答by jusep

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

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

回答by andrew

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

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

  1. Create JsonAwaraResponsethat will decode JSON response by Content-TypeHTTP 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 Middlewarewhich 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');
    
  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;
        }
    }
    
  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');
    

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

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

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

Tested with guzzlehttp/guzzle 6.3.3

用 guzzlehttp/guzzle 6.3.3 测试

回答by simPod

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

$response是 PSR-7 的实例ResponseInterface。有关更多详细信息,请参阅https://www.php-fig.org/psr/psr-7/#3-interfaces

getBody()returns StreamInterface:

getBody()返回StreamInterface

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

StreamInterfaceimplements __toString()which does

StreamInterface农具__toString()这确实

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:

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

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

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

回答by Moh

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

添加->getContents()不会返回 JSON 响应,而是作为文本返回。

You can simply use json_decode

你可以简单地使用 json_decode