суббота, 18 апреля 2015 г.

Как обоблачиться с YandexDisk - 2.5 Протокольные компоненты, часть 1. TidHTTP и JSON

§2.5. Протокольные компоненты

часть 1. TidHTTP и JSON


Часть I. Теория
2.1 Подключение ЯД к Windows
2.2 Создание папки приложения
2.3 Indy и HTTPS
2.4 Скрипач как прокси
2.5 Протокольные компоненты, часть 1. TidHTTP и JSON
2.5 Протокольные компоненты, часть 2. TREST~ и TDataSet

Чтобы работать с REST API у нас имеется множество специальных компонентов. Но в принципе достаточно иметь и не специальные, лишь бы по http(s) отправить параметры и получить текст в виде JSON, парсить который ещё проще, чем XML - у нас для этого есть прекрасный модуль (начиная с XE6) System.JSON с его TJSONObject, TJSONValue и TJSONArray. Так что же выбрать? Будем мы сосать молочко из сосочки или станем глотать молоко прямо из пакета? А если пить из пакета через трубочку? 


Давайте попробуем для начала  через компоненты HTTP запросить у Яндекс-Диска количество элементов в папке. Дело в том, что ЯД по-умолчанию выдаёт список содержания пачками по 20 штук. Разумеется, мы можем попросить выдать нам не 20, а какое-то другое количество элементов. Например - всё сразу. Но, поскольку ЯД не понимает (или я не знаю как дать ему понять), что такое "всё сразу", ему нужно сказать сколько это будет конкретно. И хорошо бы действительно знать это число, а не заказывать в параметре limit наобум 100-500 элементов.

function TForm2.GetFolderCount(const AFolder: String): Integer;
var
  LAnswer : String;
begin
  Result := 0;
  //
  with TIdHTTP.Create do
  try
    {$ifdef MSWindows}
    with ProxyParams do begin
      ProxyPort := 8888;
      ProxyServer := '127.0.0.1';
    end;
    {$endif}
    Request.CustomHeaders.AddValue( 
      'Authorization', FAuthorization );
    LAnswer := Get(
      'https://cloud-api.yandex.net/v1/disk/resources?limit=0&path='
      + HTTPEncode( AFolder ) );
    if ResponseCode <> 200 then
      Exit;
  finally  Free
  end;
  //
  with TJSONObject.ParseJSONValue( LAnswer ) as TJSONObject do
  try
    Result := ((
      GetValue( '_embedded' ) as TJSONObject ).
      GetValue( 'total' ) as TJSONNumber ).AsInt;
  finally Free;
  end;
end;
...
// calling of GetFolderCount
const
  LFolder = 'app:/';
begin
  ShowMessage( Format( '%d record(s) in folder %s', 
    [GetFolderCount( LFolder ), LFolder] ) );
...

Рассмотрим некоторые особенности кода, приведённого выше. Он делится на две части. Первая - получение информации от ЯД, вторая - обработка полученного результата. Какие замечания можно сделать по первой части?

Поскольку TIdHTTP мы создаём вручную, а не ищем его в палитре компонентов, то не забываем добавить в uses модуль IdHTTP. Если кто не знает (ну вдруг!), то можно найти компонент в палитре, кинуть на форму, всё сохранить, и удалить его - в uses будет уже всё добавлено. Работу с прокси-сервером мы как раз обсуждали чуть ранее. Думаю, очевидно, что в FAuthorization хранится наш OAuth-токенА вот что касается HTTPEncode, то для неё следует подключить модуль Web.HTTPApp. Надеюсь, вы заметили, что делая запрос мы указали в параметрах limit=0, чтобы не получать неинтересующий нас на данный момент список файлов внутри папки, а только информацию о ней самой. 

Результат запроса выглядит примерно так:


Выделенный на рисунке элемент Items - это массив записей содержимого папки. Естественно, сейчас он пуст. Итак, пора перейти ко второй части кода, где мы вытаскиваем из JSON количество файлов в папке.

Парсинг выглядит довольно просто. Однако, надо понимать следующее: память под объекты выделяется один раз - классовой функцией ParseJSONValue. Метод GetValue возвращает только ссылку на элемент в коллекции. И второе: хотя ввиду неизменности интерфейса ЯД проверять успешность получения элементов структуры особой нужды нет, в общем случае не грех завести переменную для проверки наличия результата GetValue. Имейте в виду особый порядок обработки аппаратных исключений на мобильных платформах.

to be continued...

Часть I. Теория
2.1 Подключение ЯД к Windows
2.2 Создание папки приложения
2.3 Indy и HTTPS
2.4 Скрипач как прокси
2.5 Протокольные компоненты, часть 1. TidHTTP и JSON
2.5 Протокольные компоненты, часть 2. TREST~ и TDataSet