Как правильно читать большой JSON ответ API в Guzzle 6? - PullRequest
0 голосов
/ 19 марта 2020

В настоящее время у меня есть следующая реализация Guzzle 6, возвращающая поток JSON данных, содержащих пользовательские данные:

$client = new GuzzleHttp\Client([
        'base_uri' => 'https://www.apiexample.com',
        'handler' => $oauthHandler,
        'auth'    => 'oauth',
        'headers' => [
            'Authorization' => 'Bearer xxxxxxxxxxxxxx',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
]);

$res = $client->post('example');
$stream = GuzzleHttp\Psr7\stream_for($res->getBody());

Ответы JSON выглядят так:

{
    "name": "Users",
    "record": [
        {
            "title": "Consulting",
            "_name": "Users",
            "end date": "07/03/2020",
            "session number": "1",
            "start date": "09/02/2019",
            "course id": "2900",
            "first name": "John",
            "unique user number": "123456",
            "time": "08 AM",
            "last name": "Doe",
            "year": "19-20",
            "location name": "SD"
        },
        .........
     ],
     "@extensions": "activities,corefields,u_extension,u_stu_x,s_ncea_x,s_stu_crdc_x,c_locator,u_userfields,s_edfi_x"
 }

This выполняется для нескольких клиентов, использующих разные конечные точки API. Многие из них возвращают слишком много пользователей для одновременной загрузки всего ответа JSON в ОЗУ, поэтому я использую поток.

Может быть способ заставить API возвращать порции постепенно, через несколько вызовов. Но из всего, что я получил от разработчиков API, видно, что он предназначен для использования в качестве одного потокового ответа.

Я новичок в необходимости потоковой передачи ответа API, подобного этому, и мне интересно, какой правильный подход будет перебирать записи? Глядя на документы Guzzle 6, кажется, что итерация происходит путем выбора символа x в строке и захвата этого подраздела:

http://docs.guzzlephp.org/en/stable/psr7.html#streams

use GuzzleHttp\Psr7;

$stream = Psr7\stream_for('string data');
echo $stream;
// string data
echo $stream->read(3);
// str
echo $stream->getContents();
// ing data
var_export($stream->eof());
// true
var_export($stream->tell());
// 11

Я мог бы потенциально написать что-то, что анализирует строки в подразделах посредством сопоставления с образцом и постепенно записывает данные на диск по мере продвижения по ответу. Но кажется, что это может привести к ошибкам и стать частью Guzzle 6.

Можете ли вы привести пример того, как что-то подобное должно работать, или указать, где я могу что-то упустить?

Я ценю это, спасибо!

1 Ответ

1 голос
/ 20 марта 2020

Но похоже, что это может привести к ошибкам, и это будет частью Guzzle 6.

Нет, Guzzle - это HTTP-клиент, он не имеет ничего общего с разбором разных форматы ответов.

Вам нужен потоковый парсер JSON. Пожалуйста, взгляните на этот вопрос SO , а также на библиотеки: https://github.com/salsify/jsonstreamingparser, https://github.com/clue/php-json-stream, https://github.com/halaxa/json-machine .

В Guzzle у вас будет 2 возможности:

  • , чтобы прочитать поток ответа вручную (как вы делаете в настоящее время), но это, вероятно, требует ручной интеграции с потоковым парсером JSON
  • для потоковой передачи всего ответа во временный файл (см. параметр запроса «сток» ) и чтения этого файла позже с помощью потокового парсера JSON, это должно поддерживаться всеми библиотеки.
...