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-Kaake

14
를 사용 strict_types하여 Guzzle 응답 본문을 디코딩하기 전에 문자열로 캐스팅해야했습니다.json_decode((string) $response->getBody(), true)
Yoan Tournade

나는 항상 호환되는 서명이있는 \GuzzleHttp\json_decode(또는 사용 \GuzzleHttp\Utils::jsonDecode중인 Guzzle 버전에 따라) 사용하는 것을 좋아 \json_decode했지만 오류가 있으면 적절한 오류 처리를 활용하여 예외가 발생합니다.
Adrian Föder

112

다음으로 전환하십시오.

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

객체 대신 배열을 얻기 위해 이전과 동일하게 작동하려면 다른 주석 대신.


29

$response->getBody()->getContents()응답에서 JSON을 얻는 데 사용 합니다. Guzzle 버전 6.3.0.


6
getContents()응답 본문을 호출 하면 스트림이 비워지고 다음에 대한 호출 getContents()이 비게됩니다. 몸을 끈으로 사용하려면 :strval($response->getBody())
JVitela

1
이 의견이 더 높기를 바랍니다. getContent를 사용하여 응답을 기록하고 있었고 나중에 줄을 구문 분석 할 때 배열이 비어있었습니다. 몇 시간이 걸렸습니다. 감사!
Colin

14

여전히 관심이 있다면 Guzzle 미들웨어 기능을 기반으로 한 내 해결 방법 은 다음과 같습니다.

  1. HTTP 헤더로 JsonAwaraResponseJSON 응답을 디코딩하는 작성 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


JSON이 아닌 텍스트로 JSON을 반환합니다.
František Maša
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.