गज़ल 6: प्रतिक्रियाओं के लिए कोई और जौन () विधि नहीं


172

इससे पहले गुज़्ज़ल 5.3 में:

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

मुझे आसानी से JSON प्रतिक्रिया से PHP सरणी मिल सकती है। अब गुज़ले 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, मुझे इसे डिकोड करने से पहले json_decode((string) $response->getBody(), true)
गज़ल

मुझे हमेशा उपयोग करना पसंद था \GuzzleHttp\json_decode(या आप \GuzzleHttp\Utils::jsonDecodeजिस पर गुज़ले संस्करण पर निर्भर करते हैं) का उपयोग किया गया है \json_decode, जिस पर एक संगत हस्ताक्षर है , लेकिन अगर कोई त्रुटि है, तो उचित गलत हैंडलिंग का लाभ उठाते हुए एक अपवाद फेंकता है।
एड्रियन फोदर

112

आप इस पर स्विच करते हैं:

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

अन्य टिप्पणियों के बजाय यदि आप चाहते हैं कि वस्तुओं के बजाय सरण प्राप्त करने के लिए यह पहले की तरह ही काम करे।


29

मैं $response->getBody()->getContents()प्रतिक्रिया से JSON प्राप्त करने के लिए उपयोग करता हूं । गज़ल संस्करण 6.3.0।


6
कॉलिंग getContents()प्रतिक्रिया शरीर में धारा और अगली कॉल करने के लिए खाली होगा getContents()खाली वापस आ जाएगी। यदि आप शरीर को स्ट्रिंग उपयोग के रूप में प्राप्त करना चाहते हैं:strval($response->getBody())
JVitela

1
काश यह टिप्पणी अधिक होती। मैं getContent का उपयोग करके अपनी प्रतिक्रिया लॉग कर रहा था और जब मैं बाद में एक पंक्ति को पार्स करने गया, तो मेरा सरणी खाली था। मुझे घंटे लगेंगे। धन्यवाद!
कॉलिन

14

यदि आप लोग अभी भी रुचि रखते हैं, तो यहां गुज़ले मिडलवेयर सुविधा के आधार पर मेरा वर्कअराउंड है :

  1. बनाएं JsonAwaraResponseकि द्वारा JSON उत्तर डिकोड होगा Content-Type, HTTP हेडर नहीं करता है, तो - यह मानक 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. मिडलवेयर बनाएं जो ऊपर दिए गए रिस्पॉन्स कार्यान्वयन के साथ गज़ल 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 के साथ परीक्षण किया गया


यह कुछ अच्छी वस्तु है। रेस्ट एपीआई क्लाइंट कार्य का उपयोग करना जो मैंने अभी काम में लिया था। हालांकि आपके जवाब के बारे में मेरा एक सवाल है। क्या आपका JsonAwareResponse वर्ग GuzzleHttp नामस्थान के अधीन था? मैंने अपने नामस्थान के तहत सिर्फ उस वर्ग का निर्माण किया, लेकिन एक सेकंड के लिए मैं उस वर्ग की तलाश में गुज्ज़लेहटप के कोडबेस के आसपास खोज कर रहा था। :) एक बार फिर धन्यवाद!
मंजिल

इस समाधान का उपयोग न करें क्योंकि यह PSR-7 इंटरफ़ेस को तोड़ता है MessageInterface। PSR-7 के साथ getBody()विधि से डिकोड्ड JSON को वापस करने के लिए इस इंटरफ़ेस को पैच करने के लिए कोई कानूनी समाधान नहीं है ।
सेर्गेई नेवमेरज़िट्स्की

3

$responseपीएसआर -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()


gotchas

  1. json_decode($response->getBody()सबसे अच्छा समाधान नहीं है क्योंकि यह जादुई रूप से आपके लिए स्ट्रिंग में स्ट्रीम करता है। json_decode()1 तर्क के रूप में स्ट्रिंग की आवश्यकता है।
  2. $response->getBody()->getContents()जब तक आपको पता नहीं चलेगा कि आप क्या कर रहे हैं। यदि आप getContents()इसके लिए प्रलेखन पढ़ते हैं , तो यह कहता है Returns the remaining contents in a string:। इसलिए, कॉलिंग getContents()स्ट्रीम के बाकी हिस्सों को पढ़ता है और कॉलिंग फिर से कुछ भी नहीं देता है क्योंकि स्ट्रीम पहले से ही अंत में है। आपको उन कॉलों के बीच स्ट्रीम को रिवाइंड करना होगा।

1

जोड़ना ->getContents()jSON प्रतिक्रिया नहीं देता है, इसके बजाय यह पाठ के रूप में लौटता है।

आप बस उपयोग कर सकते हैं json_decode


यह JSON को टेक्स्ट के रूप में लौटाता है, HTML को नहीं।
फ्रांटिसेक माचा
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.