Сервис импорта и экспорта данных в XML/JSON

Функции сервиса

Сервис экспорта и импорта данных предоставляет программный интерфейс к отчетам, формам и реестрам (в дальнейшем просто отчетам) системы.

В данный момент есть две версии API - 1-ая и 2-ая. 1-ая более универсальная, поддерживает импорт и экспорт, не требует никакой дополнительной настройки со стороны Netdb, но менее удобна для использования внешними системами. 2-ая версия поддерживает только экспорт и требует дополнительной настройки, зато предоставляет удобное для потребление API, которое также удобно поддерживать со стороны Netdb.

Сценарий работы

Система выступает в роли сервера, а внешняя ИС - в роли клиента.

1. Зарегистрировать внешнюю ИС как пользователя, для чего обратиться к администратору системы. Права этого пользователя в системе определяют возможности внешней ИС при импорте и экспорте.

2. Зайти в систему от имени вновь зарегистрированного пользователя, перейти на страницу редактирования профиля, и нажать кнопку “Сгенерировать ключ авторизации”. Этот ключ в дальнейшем будет использоваться для авторизации всех запросов внешней ИС.

3. Найти или построить отчет, с которым нужно работать. Определить идентификатор отчета, наличие у него параметров и значения параметров, которые планируется использовать.

4. Проверить, что данный отчет доступен для чтения или записи пользователю, от имени которого будет работать внешняя ИС.

5. Использовать API для экспорта или импорта - тема остальной части документа.

Авторизация

Авторизация для сервисов экспорта и импорта происходит одинаково: при совершении запроса нужно выставить в HTTP-заголовке Netdb-Api-Key ключ авторизации. Этот ключ нужно создать на странице редактирования профиля пользователя в web-интерфейсе системы. Он действует до тех пор, пока сам пользователь не захочет его обновить.

При ошибке авторизации возвращается ответ со статусом 401, в xml:

<?xml version="1.0" encoding="UTF-8"?>
<error kind="auth">
</error>

Экспорт (версия 1)

Метод:

GET

URL:

/api/1/<id>/, где вместо <id> нужно подставить id отчета, который нужно экспортировать. В интерфейсе системы идентификатор - это последние цифры в url страницы

GET:

в get-параметрах запроса необходимо указать значения всех параметров отчета, если они есть. Ключи для всех параметров называются param, они должны следовать в том же порядке, что и параметры при просмотре отчета. Формат параметров описан ниже, в отдельном разделе.

Пример get-параметров для отчета с двумя параметрами: param=123&param=789989. По умолчанию отчет экспортируется без заголовков (верхних и боковика). При необходимости включить заголовки нужно добавить параметр headers с любым значением. Тогда get-параметры будут выглядеть так: param=123&param=789989&headers=true.

Пример запроса к серверу по адресу http://system.sample.com для экспорта отчета с id = 34678 и с двумя параметрами:

GET /api/1/?param=123&param=457 HTTP/1.1
Host: system.sample.com
Accept: text/xml
Connection: close
Netdb-Api-Key: fasdf6sa7df8sdf67d8df687f6dfdaa

Ответ приходит в xml. При успешном экспорте ответ содержит элемент верхнего уровня data, элемент params (если у отчета есть параметры - в них перечислены параметры, которые были в get-запросе), и элемент table, устроенный как таблица в HTML. В tr лежат строки, а сами значения содержатся в элементах td:

<?xml version="1.0" encoding="UTF-8"?>
<data>
  <params>
    <param>123</param>
    <param>789989</param>
  </params>
  <table>
    <tr>
      <td></td>
      <td>55</td>
      <td>59</td>
    </tr>
    <tr>
      <td>88</td>
      <td>99</td>
      <td>890</td>
    </tr>
    <tr>
      <td>44</td>
      <td>55</td>
      <td></td>
    </tr>
  </table>
</data>

Если для построения запрошен отчет с заголовками (в get-параметрах есть headers), то заголовки будут обозначены элементами th, у которых могут быть атрибуты rowspan и colspan - их смысл аналогичен атрибутам тега th в HTML. Пример:

<?xml version="1.0" encoding="UTF-8"?>
<data>
  <params>
    <param>123</param>
    <param>789989</param>
  </params>
  <table>
    <tr>
      <th colspan="2">Общий заголовок</th>
    </tr>
    <tr>
      <th>Первый столбец</th>
      <th>Второй столбец</th>
    </tr>
    <tr>
      <th rowspan="2">Первые две строки</th>
      <th>Первая строка</th>
      <td></td>
      <td>55</td>
      <td>59</td>
    </tr>
    <tr>
      <th>Вторая строка</th>
      <td>88</td>
      <td>99</td>
      <td>890</td>
    </tr>
    <tr>
      <th colspan="2">Третья строка</th>
      <td>44</td>
      <td>55</td>
      <td></td>
    </tr>
  </table>
</data>

Если в клетке есть значение, но у пользователя, от которого производится операция, нет прав на его просмотр, то в клетке будет пусто.

При неправильном количестве параметров возвращается ответ со статусом 400:

<?xml version="1.0" encoding="UTF-8"?>
<error kind="params">
  Ожидалось параметров: 3, получено параметров: 0
</error>

При ошибке в формате значений параметров возвращается ответ со статусом 400, который содержит исходные значения параметров и пояснение об ошибке:

<?xml version="1.0" encoding="UTF-8"?>
<error kind="value_format">
  <params>
    <param>97896</param>
    <param error="Введите дату в формате...">2011</param>
  </params>
</error>

Если в запросе указан <id> несуществующего отчета, то возвращается ответ со статусом 404 следующего вида:

<?xml version="1.0" encoding="UTF-8"?>
<error kind="invalid_request">
  Отчет, реестр или форма не найдены
</error>

Для тестирования экспорта отчета из интерфейса (без параметров) можно использовать адрес /report-to-xml/<id>/.

Экспорт (версия 2)

Метод:GET
URL:/api/2/<id>.<format>, где вместо <id> нужно подставить или id, или название отчета, который нужно экспортировать, а <format> может быть xml или json, если расширение опущено, подразумевается json формат
GET:get-параметрах запроса необходимо указать значения параметров. При настройке отчета название каждого параметра задается в поле “Метка” или “Название”. Формат значений параметров описан ниже. Все параметры не обязательны, при отсутствии параметра берется значение по умолчанию (но пустое значение - это не отсутствие параметра!). Неизвестные GET-параметры считаются ошибкой.

В отличии от API версии 1, которое работает для любого отчета, для версии 2 как правило необходима дополнительная настройка отчета - задание названий заголовков, которые должны быть валидными xml аттрибутами или ключами в json, задание названия отчета, названий параметров.

Если клиент запросил отчет в формате xml, и в отчете есть колонки с названиями geo, kfh, skh, и название отчета xmltest, то ответ будет иметь следующий вид:

<xmltest>
    <item geo="3950" kfh="146" skh="303"/>
    <item geo="11157" kfh="" skh="34"/>
    <item geo="34756" kfh="" skh=""/>
</xmltest>

Тот же самый отчет в формате json имеет вид:

{
    "items": [
        {"geo": 3950, "skh": 303, "kfh": 146},
        {"geo": 11157, "skh": 34, "kfh": null},
        {"geo": 34756, "skh": null, "kfh": null}
    ]
}

API версии 2 никогда не выгружает заголовки - при необходимости их выгрузки нужно добавить их в отчет как источники с опцией “брать значение из фильтра”.

При экспоре реестра к каждому тэгу (или элементу) добавляется аттрибут id, содержащий внутренний идентификатор элемента. Его нет в отчетах, т.к. отчет представляет собой результат некоторых вычислений, а реестр - всегда выборку исходных данных, где одной строке соответствует один объект.

Для тестирования экспорта отчета из интерфейса (без параметров и только по id) можно использовать адреса /report-to-xml/2/<id>/, /report-to-json/2/<id/.

Импорт (версия 1)

Метод:POST
URL:/api/1/<id>/, где вместо <id> нужно подставить id отчета, которую нужно экспортировать. В интерфейсе системы идентификатор - это последние цифры в url страницы
тело:в формате application/x-www-form-urlencoded, по единственному ключу data отдаются данные в xml-формате (описан ниже)

Элемент верхнего уровня - data. Если у отчета есть параметры, то первый вложенный элемент - params. Внутри него должно быть столько элементов param, сколько есть параметров у отчета. Внутри элемента param указывается значение соответствующего параметра отчета. Если параметров нет, то и элемента params быть не должно, а его наличие будет считаться ошибкой.

Далее следует обязательный элемент table, организованный как в HTML. Внутри него должно быть столько элементов tr, сколько есть строк в отчете. Внутри каждого tr должно быть столько td, сколько в отчете столбцов. Внутри каждого td указываются значение в данной клетке отчета. Если значение пустое (пустая строка), а в системе в этой клетке есть значение, то подразумевается удаление этого значения.

Пример данных в формате xml для отчета с двумя параметрами, четырьмя строчками и тремя столбцами:

<?xml version="1.0" encoding="UTF-8"?>
<data>
  <params>
    <param>97896</param>
    <param>2011 г.</param>
  </params>
  <table>
    <tr>
      <td></td>
      <td>55</td>
      <td>59</td>
    </tr>
    <tr>
      <td>88</td>
      <td>99</td>
      <td>890</td>
    </tr>
    <tr>
      <td>44</td>
      <td>55</td>
      <td></td>
    </tr>
  </table>
</data>

Ответ от сервера приходит со статусом 200 или 400 в зависимости от успешности выполнения запроса клиента. При успешном импорте данных возвращается ответ следующего вида (в атрибутах updated, created и deleted указано соответственно число обновленных, созданных и удаленных объектов):

<?xml version="1.0" encoding="UTF-8"?>
<data updated="6" created="1" deleted="1">
</data>

При ошибке в формате xml (невалидный, или не хватает элементов и т.п.):

<?xml version="1.0" encoding="UTF-8"?>
<error kind="invalid_request">
  Невалидный xml (или не найден элемент data, или неправильный table).
  Или любое другое пояснение
</error>

При ошибке в формате значений (не важно, параметров или клеток) возвращается исходный запрос в элементе error, где к ошибочным полям (элементы params или td) добавлен атрибут error, поясняющий смысл ошибки (текст ошибки аналогичен тексту ошибок в web-интерфейсе системы). При ошибке в правах доступа к полям (к элементу td) добавляется атрибут permission_error:

<?xml version="1.0" encoding="UTF-8"?>
<error kind="value_format">
  <params>
    <param>97896</param>
    <param error="Введите дату в формате...">2011</param>
  </params>
  <table>
    <tr>
      <td></td>
      <td error="Введите целое число">78.3</td>
      <td>59</td>
    </tr>
    <tr>
      <td permission_error="У вас нет прав на запись в показатель...">88</td>
      <td>99</td>
      <td>890</td>
    </tr>
    <tr>
      <td>44</td>
      <td>55</td>
      <td></td>
    </tr>
  </table>
</error>

При наличии хотя бы одной ошибки сохранение данных не происходит.

Импорт в реестры (версия 1)

Реестры (которые в остальной части документа считаются частным случаем отчетов) отличаются от отчетов тем, что у них не задано количество строк.

Пример запроса на импорт

<?xml version="1.0" encoding="UTF-8"?>
<data>
  <params>
    <param>97896</param>
  </params>
  <table>
    <tr>
      <td>218</td>
      <td>55.238</td>
      <td>2010 г.</td>
    </tr>
    <tr>
      <td>218</td>
      <td>57.813</td>
      <td>2011 г.</td>
    </tr>
  </table>
</data>

В структуре реестра может быть задан некоторое набор столбцов, которые образуют ключ. Если такой набор столбцов задан, и для данной записи при импорте в этом реестре находится запись с такими же значениями ключевых столбцов, то происходит обновление этой записи. Если же такой записи нет, или ключ не указаны, происходит добавление записи в реестр.

Ответ от сервера приходит со статусом 200 или 400 в зависимости от успешности выполнения запроса клиента.

В остальном импорт в реестры происходит так же, как импорт в отчеты или формы.

Импорт (версия 2)

API версии 2 не поддерживает импорт в настоящий момент.

Форматы значений данных и параметров

Форматы и примеры для всех типов значений, которые используются в данных (в элементах td), или в значениях параметров (в элементах param):

Число:“3.14159265” - десятичное число с плавающей точкой, разделитель точка или запятая, можно в экспоненциальном формате: “6.022e23”.
Целое число:“60” - десятичное число, может быть отрицательным: “-127”.
Объект:“34598754” - идентификатор объекта, целое число (может быть отрицательным). Идентификатор объекта можно узнать на странице объекта в соответствующем справочнике.
Период:“17.01.2012 (неделя)” - описание форматов см. ниже

Форматы типов периодов:

год:2012 г.
3 квартала:1 кв. 2012 г. - 3 кв. 2012 г.
полугодие:1 п. 2012 г.
квартал:1 кв. 2012 г.
месяц:январь 2012 г.
декада:2 декада января 2012 г.
неделя:с 17.01.2012 по 24.01.2012
день:17.01.2012, 2012-01-17

Смысл типов периодов:

год:год, начало 1 января, конец 1 января след. года.
3 квартала:3 квартала, начинаются в один из кварталов
полугодие:полугодие, начинается 01.01 или 01.07.
квартал:квартал, начинается 01.01, 01.04, 01.07 или 01.10.
месяц:месяц, начинается 1 числа месяца
декада:декада, каждый месяц состоит из трех декад, начинается 1, 11, или 21 числа месяца
неделя:неделя, 7 дней, начинается в любой день
день:день, начинается и заканчивается в 00:00

Пример использования сервиса из коммандной строки

Экспорт, 1-ая версия:

curl -H 'Netdb-Api-Key: EBVFrPEOdF' \
    'http://somename.chtd.ru/api/1/871/?param=март+2011+г.&headers=true'

Экспорт, 2-ая версия:

curl -H 'Netdb-Api-Key: EBVFrPEOdF' \
    'http://somename.chtd.ru/api/2/somereport?day=2011-10-01'