В статье «Начинаем работать с REST и PowerShell», опубликованной в предыдущем номере журнала, мы рассмотрели пример получения данных о высоте уровня воды в реке почти в реальном времени от службы RESTful. Для доступа к службе RESTful использовалась команда Invoke-WebRequest, а из данных, возвращаемых веб-службой в формате XML, с помощью Xpath извлекалось нужное значение. В этой статье будет показано, как с помощью команды Invoke-RestMethod получить необходимые данные от службы геопозиционирования RESTful от Bing, поставляющей данные в формате JavaScript Object Notation (JSON), а не XML.

Служба геопозиционирования Bing преобразует пары «широта-долгота» в адреса и обратно через интерфейс RESTful. Вы можете бесплатно запрашивать Bing до 125 тыс. раз, но только при условии приобретения ключа Bing Maps (для этого необходимо зарегистрироваться со своей учетной записью Microsoft). Ключ выглядит так: P8xPNZEHQTY9fKoDRw0NyOjysoCN3zV-Tbh-AEQBNkRSk8fsPg9916a9gOL7cQ, но в примерах ниже я буду использовать BingKey. По почтовому индексу 12345 запросим город, страну и штат привычным для всех способом, а именно путем ввода универсального кода ресурса (URI) в адресной строке браузера:

http://dev.virtualearth.net/REST/v1/Locations? q=
   12345,%20 USA&key=BingKey

В ответ на этот запрос получаем очень длинную строку текста в формате JSON (см. экран 1).

 

Строка текста в формате JSON
Экран 1. Строка текста в формате JSON

 

В ней locality, adminDistrict2, adminDistrict и countryRegion означают город, административный округ, штат и страну соответственно. Если заменить 12345 каким-либо другим пятизначным значением, то будет возвращено только название страны, countryRegion (это означает, что Bing не смог найти ответ; очевидно, поиск по почтовому индексу не такая простая задача), или значения соответствующих этому почтовому индексу города, штата и т. д.

Как и в случае с текстом XML, возвращаемая длинная строка в формате JSON — это текстовый способ представления объектов данных. Мы не ставим перед собой задачу изучения синтаксического анализа или создания XML или JSON, но минимальное знакомство с этими форматами может оказаться полезным, поэтому рассмотрим их на примере простого объекта данных (см. рисунок).

 

Простой объект данных
Рисунок. Простой объект данных

 

Этот объект я назвал Creatures («Животные»). Животные на данной схеме подразделяются на три категории, каждая из которых имеет атрибут type («Тип»), принимающий значение fish («Рыбы»), amphibians («Земноводные») и mammals («Млекопитающие»). Заметим, что запись type ничего не означает для XML или JSON; это просто слово, которое я выбрал. В рамках классификации Линнея, возможно, больше бы подошел термин Class («Класс»). Каждый тип подразделяется на два подтипа, классифицируемые по типу крови (теплокровные и холоднокровные) и количеству камер сердца. В формате XML эти данные выглядят так, как показано на экране 2.

 

Данные объекта в формате XML
Экран 2. Данные объекта в формате XML

 

Сравним это представление с представлением той же классификации животных в формате JSON (см. экран 3).

 

Данные объекта в формате JSON
Экран 3. Данные объекта в формате JSON

 

Оба формата справляются с задачей по-разному. После предварительного анализа ясно, что JSON для описания объектов использует фигурные скобки ({}) и массивы в квадратных скобках ([]), элементы которых (в нашем случае — три типа животных) разделены запятыми.

К сожалению, реальные веб-службы выдают данные JSON в виде длинной строки текста, а не удобной для восприятия структуры, показанной в нашем примере. Это может затруднять поиск нужных данных, если не прибегнуть к помощи подключаемого модуля Chrome под названием JSON Formatter (или JSONView — для пользователей Firefox). У Internet Explorer модуль структурной распечатки отсутствует, поэтому я предпочитаю не использовать IE с JSON.

Структурная печать важна, поскольку позволяет получить иерархическое представление, которое помогает извлечь нужные данные. Реализованная в PowerShell поддержка JSON не предусматривает чего-либо, подобного Xpath. Фрагмент структурной распечатки данных, полученных в ответ на запрос по почтовому индексу 12345, показан на экране 4. Здесь хорошо видно, что объект resourceSets содержит объект по имени resources, который содержит объект по имени address, а тот в свою очередь содержит нужные нам объекты adminDistrict (административный округ), adminDistrict2 (штат) и locality (город). Будь это объект PowerShell, мы бы смогли извлечь locality с помощью точечной нотации

$somevariable.resourceSets.resources.address.locality

 

Ответ на запрос по почтовому индексу
Экран 4. Ответ на запрос по почтовому индексу

 

Однако мы имеем дело с объектом JSON, а не PowerShell, и именно здесь нам пригодится команда Invoke-RestMethod, которая, по сути, является дубликатом Invoke-WebRequest, за исключением того, что она ориентирована на объекты JSON и автоматически представляет их в виде объекта PowerShell:

$URI = " http://dev.virtualearth.net/REST/v1/Locations? q=
   12345,%20 USA&key=BingKey"
$Result = Invoke-RestMethod $URI

Теперь объекты JSON «живут» в переменной $Result как объекты PowerShell. Для того чтобы вывести искомый город (locality), достаточно ввести

$Result.resourceSets.resources.address.locality

Словом, если выяснится, что веб-служба в ответ на запрос выдает данные в формате JSON, взгляните на структурную распечатку этих данных, чтобы узнать иерархию объекта, а затем с помощью Invoke-RestMethod преобразуйте данные JSON в объект PowerShell и примените точечную нотацию PowerShell для извлечения желаемого элемента.