Hướng dẫn 6: không có phương thức json () để trả lời


172

Trước đây trong Gu khó 5.3:

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

Tôi có thể dễ dàng nhận được một mảng PHP từ một phản hồi JSON. Bây giờ trong Gu 6, tôi không biết làm thế nào. Dường như không còn json()phương pháp nào nữa. Tôi (nhanh chóng) đọc tài liệu từ phiên bản mới nhất và không tìm thấy gì về phản hồi JSON. Tôi nghĩ rằng tôi đã bỏ lỡ điều gì đó, có thể có một khái niệm mới mà tôi không hiểu (hoặc có thể tôi đã không đọc chính xác).

Đây có phải là cách mới dưới đây không?

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

Hoặc có một người trợ giúp hoặc một cái gì đó như thế?

Câu trả lời:


292

Tôi sử dụng json_decode($response->getBody())bây giờ thay vì $response->json().

Tôi nghi ngờ đây có thể là một tai nạn của việc tuân thủ PSR-7.


4
Không có gì trong tài liệu làm cho điều này rõ ràng nhưng có vẻ như họ đã loại bỏ người $response->json()trợ giúp.
kẹp giấy

60
Nếu bạn đang mong đợi một phản hồi mảng như cách hoạt động của bản gốc ->json(), json_decode($response->getBody(), true)thay vào đó hãy sử dụng để lấy một mảng thay vì stdObject
Jay El-Kaake

14
Sử dụng strict_types, tôi cần phải sử dụng cơ thể phản hồi của Guheads thành chuỗi trước khi giải mã nó:json_decode((string) $response->getBody(), true)
Yoan Tournade

112

Bạn chuyển sang:

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

Thay vì các bình luận khác nếu bạn muốn nó hoạt động chính xác như trước để có được các mảng thay vì các đối tượng.


29

Tôi sử dụng $response->getBody()->getContents()để nhận JSON từ phản hồi. Phiên bản hướng dẫn 6.3.0.


6
Cuộc gọi getContents()trong phần thân phản hồi sẽ làm trống luồng và cuộc gọi tiếp theo getContents()sẽ trả về trống. Nếu bạn muốn lấy cơ thể dưới dạng chuỗi, hãy sử dụng:strval($response->getBody())
JVitela

1
Tôi muốn bình luận này cao hơn. Tôi đã ghi lại phản hồi của mình bằng getContent và khi tôi đi phân tích một dòng sau đó, mảng của tôi trống. Chi phí cho tôi hàng giờ. Cảm ơn!
Colin

14

Nếu các bạn vẫn quan tâm, đây là cách giải quyết của tôi dựa trên phần mềm trung gian Guheads tính năng :

  1. Tạo JsonAwaraResponsesẽ giải mã phản hồi JSON bằng Content-Typetiêu đề HTTP, nếu không - nó sẽ hoạt động như Phản hồi theo tiêu chuẩn:

    <?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. Tạo Middleware sẽ thay thế các phản hồi Guzz PSR-7 bằng cách thực hiện Phản hồi ở trên:

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

Sau này để lấy JSON như mảng gốc PHP, hãy sử dụng Guheads như mọi khi:

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

Đã thử nghiệm với guzzhttp / gu khó 6.3.3


Đây là một số công cụ tốt. Sử dụng trong tác vụ Máy khách API còn lại mà tôi vừa chọn tại nơi làm việc. Tôi có một câu hỏi về câu trả lời của bạn mặc dù. Có phải lớp JsonAwareResponse của bạn được dự định ở dưới không gian tên GuheadsHttp? Cuối cùng tôi đã tạo ra lớp đó trong không gian tên của riêng mình, nhưng trong một giây, tôi đã tìm kiếm xung quanh cơ sở mã của GuheadsHttp để tìm lớp đó. :) Cảm ơn một lần nữa!
floorz

Không sử dụng giải pháp này vì nó phá vỡ giao diện PSR-7 MessageInterface. Với PSR-7, không có giải pháp pháp lý nào để vá giao diện này để trả về JSON được giải mã từ getBody()phương thức.
Serge Nevmerzhitsky

3

$responselà ví dụ của PSR-7 ResponseInterface. Để biết thêm chi tiết, hãy xem https://www.php-fig.org/psr/psr-7/#3-interfaces

getBody()trả về StreamInterface:

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

StreamInterfacethực hiện __toString()

Đọc tất cả dữ liệu từ luồng thành một chuỗi, từ đầu đến cuối.

Do đó, để đọc phần thân dưới dạng chuỗi, bạn phải chuyển nó thành chuỗi:

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


Gotchas

  1. json_decode($response->getBody()không phải là giải pháp tốt nhất vì nó kỳ diệu truyền thành chuỗi cho bạn. json_decode()yêu cầu chuỗi là đối số thứ nhất.
  2. Đừng sử dụng $response->getBody()->getContents()trừ khi bạn biết bạn đang làm gì. Nếu bạn đọc tài liệu cho getContents(), nó nói : Returns the remaining contents in a string. Do đó, việc gọi getContents()đọc phần còn lại của luồng và gọi lại sẽ không trả về gì vì luồng đã ở cuối. Bạn sẽ phải tua lại luồng giữa các cuộc gọi đó.

1

Thêm ->getContents()không trả lại phản hồi jSON, thay vào đó nó trả về dưới dạng văn bản.

Bạn chỉ có thể sử dụng json_decode


Nó trả về JSON dưới dạng văn bản, không phải HTML.
František Maša
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.