Как реализовать отчет на СКД, получающий данные из внешнего API через JSON?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В современной разработке на платформе 1С все чаще возникает задача построения отчетов, данные для которых находятся не в локальной базе данных, а во внешних сервисах — CRM-системах, сайтах поставщиков или государственных информационных системах. Система компоновки данных (СКД) предоставляет гибкие механизмы для работы с такими источниками. Разберем подробно процесс создания такого отчета: от выполнения HTTP-запроса до вывода данных в стандартную форму компоновки.

Общая архитектура решения

Для того чтобы данные из стороннего сервиса попали в отчет СКД, нам необходимо пройти через несколько этапов:

  1. Установка соединения: создание объекта HTTPСоединение и выполнение запроса.
  2. Получение ответа: считывание тела ответа (обычно в формате JSON).
  3. Десериализация: преобразование строки JSON в коллекции 1С (Массив, Структура) или дерево объектов XDTO.
  4. Подготовка таблицы: перенос данных в ТаблицаЗначений с явным приведением типов.
  5. Передача в СКД: использование механизма "Внешний набор данных".

Шаг 1: Получение данных через HTTP-запрос

Проанализируем процесс взаимодействия с API. Для работы с большинством современных сервисов используется протокол HTTPS. Рассмотрим пример кода, который выполняет GET-запрос к API:


// Настройка защищенного соединения (для HTTPS)
Защита = Новый ЗащищенноеСоединениеOpenSSL();
// Создаем соединение с сервером
Соединение = Новый HTTPСоединение("api.external-site.com", , , , , 30, Защита);

// Формируем запрос с необходимыми заголовками
Запрос = Новый HTTPЗапрос("/v1/data?limit=100");
Запрос.Заголовки.Вставить("Content-Type", "application/json");
Запрос.Заголовки.Вставить("Authorization", "Bearer " + ТокенДоступа);

Попытка
    Ответ = Соединение.Получить(Запрос);
    Если Ответ.КодСостояния <> 200 Тогда
        ВызватьИсключение "Ошибка API: " + Ответ.КодСостояния;
    КонецЕсли;
    СтрокаJSON = Ответ.ПолучитьТелоКакСтроку();
Исключение
    Сообщить("Не удалось получить данные: " + ОписаниеОшибки());
    Возврат;
КонецПопытки;

Обратите внимание на использование тайм-аутов в HTTPСоединение. Это критически важно, чтобы при задержках на стороне сервера сеанс пользователя не "завис" на неопределенное время.

Шаг 2: Обработка JSON и заполнение таблицы значений

Полученную строку JSON необходимо превратить в данные, понятные 1С. Мы можем использовать либо прямой парсинг в структуры и массивы, либо воспользоваться ФабрикаXDTO, если у нас есть сложная иерархия данных. Разберем наиболее универсальный способ через ЧтениеJSON.

Важный нюанс: данные в JSON часто нетипизированы (все передается строками). Для корректной работы сортировок и итогов в СКД мы должны явно типизировать колонки нашей таблицы.


// Создаем структуру таблицы значений
ТЗ_Данные = Новый ТаблицаЗначений;
ТЗ_Данные.Колонки.Добавить("Идентификатор", Новый ОписаниеТипов("Число"));
ТЗ_Данные.Колонки.Добавить("Наименование",  Новый ОписаниеТипов("Строка"));
ТЗ_Данные.Колонки.Добавить("ДатаСобытия",   Новый ОписаниеТипов("Дата"));
ТЗ_Данные.Колонки.Добавить("Сумма",         Новый ОписаниеТипов("Число"));

// Парсим JSON
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(СтрокаJSON);
ДанныеИзAPI = ПрочитатьJSON(ЧтениеJSON); // Получаем массив структур
ЧтениеJSON.Закрыть();

// Заполняем таблицу значений
Для Каждого Элемент Из ДанныеИзAPI.items Цикл
    НоваяСтрока = ТЗ_Данные.Добавить();
    НоваяСтрока.Идентификатор = Число(Элемент.id);
    НоваяСтрока.Наименование  = Строка(Элемент.name);
    
    // Обработка даты в формате ISO 8601
    СтрДата = СтрЗаменить(Элемент.date, "T", "");
    НоваяСтрока.ДатаСобытия = XMLЗначение(Тип("Дата"), СтрДата);
    
    НоваяСтрока.Сумма = Элемент.amount;
КонецЦикла;

Шаг 3: Настройка СКД (Внешний набор данных)

В схеме компоновки данных (открываем в конфигураторе) вместо привычного "Набора данных - запрос" мы должны добавить Набор данных - объект. Выполним следующие шаги:

  1. Укажите Имя объекта содержащего данные (например, "ТаблицаВнешнихДанных"). Это имя будет использоваться в коде модуля.
  2. Добавьте поля вручную, указав их имена и типы в строгом соответствии с колонками нашей ТаблицаЗначений.
  3. Настройте ресурсы (например, сумму), параметры и настройки отчета как обычно.

Шаг 4: Программная передача данных в СКД

Поскольку данные находятся во внешней таблице, стандартный механизм формирования отчета не сработает автоматически. Нам нужно переопределить процедуру ПриКомпоновкеРезультата в модуле отчета.


Процедура ПриКомпоновкеРезультата(ДанныеРасшифровки, СтандартнаяОбработка)
    
    СтандартнаяОбработка = Ложь;
    
    // 1. Получаем данные из API (вызываем написанную ранее функцию)
    ТаблицаДанных = ПолучитьДанныеИзAPI(); 
    
    // 2. Создаем структуру для передачи внешних наборов
    ВнешниеНаборыДанных = Новый Структура;
    ВнешниеНаборыДанных.Вставить("ТаблицаВнешнихДанных", ТаблицаДанных);
    
    // 3. Выполняем стандартную компоновку программно
    СхемаКомпоновкиДанных = ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
    Настройки = КомпоновщикНастроек.ПолучитьНастройки();
    
    КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
    МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки, ДанныеРасшифровки);
    
    ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
    ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, ВнешниеНаборыДанных, ДанныеРасшифровки);
    
    ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
    ПроцессорВывода.УстановитьДокумент(Результат);
    ПроцессорВывода.Вывести(ПроцессорКомпоновки);
    
КонецПроцедуры

Оптимизация и важные дополнения

Рассмотрим несколько продвинутых техник, которые сделают ваш отчет профессиональным:

Пагинация (Постраничная загрузка)

Если API возвращает тысячи записей, оно, скорее всего, отдаст их частями. Проанализируем, как реализовать цикл загрузки:


Пока Истина Цикл
    // Добавляем параметры смещения в URL
    Запрос.АдресРесурса = "/v1/data?offset=" + ТекущийОфсет;
    // ... получение и парсинг данных ...
    Если ДанныеИзAPI.Count() = 0 Тогда
        Прервать; // Данных больше нет
    КонецЕсли;
    // ... заполнение таблицы ...
    ТекущийОфсет = ТекущийОфсет + ДанныеИзAPI.Count();
КонецЦикла;

Обработка лимитов (Rate Limiting)

Если сервер возвращает ошибку 429 (Too Many Requests), нам необходимо приостановить выполнение. Выясним, как это сделать:


Если Ответ.КодСостояния = 429 Тогда
    // Ждем 1 секунду перед повторной попыткой
    Приостановить(1); 
    // Здесь должна быть логика повтора запроса
КонецЕсли;

Кэширование данных

Запросы к внешним API могут быть медленными. Если данные не требуют обновления в режиме реального времени, рекомендуется сохранять результат запроса во ВременноеХранилище или в специальный служебный РегистрСведений. Это позволит пользователям мгновенно переформировывать отчет, меняя только группировки или отборы в СКД, без повторных сетевых обращений.

Использование связки СКД и внешних API позволяет создавать мощные инструменты мониторинга и анализа, объединяя данные из различных информационных систем в едином интерфейсе 1С.

← На главную