Как правильно выгрузить данные из JSON (API) в табличную часть документа в 1С?

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

При интеграции 1С со сторонними сервисами (например, телефонией Бинотел) разработчики часто сталкиваются с задачей получения данных по API в формате JSON и их последующей выгрузкой в табличную часть документа. Рассмотрим классическую ситуацию: мы получаем массив записей (например, историю звонков) и хотим поместить каждую запись в отдельную строку табличной части. Разберем по шагам, как избежать архитектурных ошибок, оптимизировать код и использовать встроенные механизмы платформы.

Анализ изначального (ошибочного) подхода

Часто начинающие программисты пытаются для каждой записи из JSON создавать отдельную локальную таблицу значений (Новый ТаблицаЗначений), заполнять ее, а затем переносить данные в табличную часть документа. Проанализируем, почему этот подход не является оптимальным:

  1. Создание нового объекта ТаблицаЗначений в цикле для каждой записи — это лишняя трата ресурсов системы.
  2. Перенос данных из локальной таблицы в реквизит объекта (табличную часть) требует дополнительного неоправданного обхода или явного обращения по индексам.
  3. Код становится громоздким и трудночитаемым.

Посмотрим на более изящные и правильные способы решения этой задачи.

Решение 1: Прямое присвоение или обращение по ключу

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


&НаСервере
Процедура ЧтениеДанныхЗвонков(ТекСтрокаЗвонок)
    СтрокаТаблицыЗвонков = Объект.ТаблицаЗвонков.Добавить();
    Для Каждого ТекСтрокаДанныеЗвонка Из ТекСтрокаЗвонок.Значение Цикл
        // Обращаемся к колонке табличной части по имени ключа
        СтрокаТаблицыЗвонков[ТекСтрокаДанныеЗвонка.Ключ] = ТекСтрокаДанныеЗвонка.Значение;
    КонецЦикла;
КонецПроцедуры

Если имена не совпадают, мы можем явно указывать соответствие колонок:


&НаСервере
Процедура ЧтениеДанныхЗвонков(ТекСтрокаЗвонок)
    СтрокаТаблицыЗвонков = Объект.ТаблицаЗвонков.Добавить();
    СтрокаТаблицыЗвонков.Телефон = ТекСтрокаЗвонок["phone"];
    СтрокаТаблицыЗвонков.Длительность = ТекСтрокаЗвонок["duration"];
КонецПроцедуры

Решение 2: Использование метода ЗаполнитьЗначенияСвойств (Лучшая практика)

Платформа 1С предоставляет мощный встроенный метод ЗаполнитьЗначенияСвойств. Он позволяет скопировать значения из структуры (полученной из JSON) прямо в строку табличной части одной строкой кода. Главное условие — ключи структуры должны совпадать с именами колонок. Посмотрим на переработанный пример основной процедуры получения звонков:


&НаСервере
Процедура КомандаПолучитьЗвонкиНаСервере()
    ДокументОбъект = РеквизитФормыВЗначение("Объект");
    
    // Получение данных по API
    startTime = ДокументОбъект.ПолучитьUnixTS(Объект.startTime);
    stopTime = ДокументОбъект.ПолучитьUnixTS(Объект.stopTime);
    ПолучитьЗвонки = ДокументОбъект.IncomingCallsForPeriod(Объект.key, Объект.secret, startTime, stopTime);
    
    Текст = Новый ЧтениеТекста(ПолучитьЗвонки, КодировкаТекста.UTF8);
    СтруктураJSON = ДокументОбъект.ПрочитатьJSON_API(Текст.Прочитать(), Неопределено);
    
    СтруктураЗвонков = Неопределено;
    // Используем Свойство() вместо Попытка...Исключение (об этом ниже)
    Если Не СтруктураJSON.Свойство("callDetails", СтруктураЗвонков) Тогда
        Возврат;
    КонецЕсли;

    // Очищаем табличную часть перед заполнением
    Объект.ТаблицаЗвонков.Очистить();
    
    // Обходим каждый звонок и заполняем ТЧ
    Для Каждого Запись Из СтруктураЗвонков Цикл
        СтрокаТаблицыЗвонков = Объект.ТаблицаЗвонков.Добавить();
        ЗаполнитьЗначенияСвойств(СтрокаТаблицыЗвонков, Запись);
        
        // Дозаполнение свойств, которых нет в JSON
        СтрокаТаблицыЗвонков.isNewCall = Истина;
    КонецЦикла;
КонецПроцедуры

Решение 3: Оптимизация массовой загрузки (Метод Загрузить)

Если API возвращает сотни или тысячи записей, добавление строк в цикле через Добавить() может замедлить работу интерфейса и сервера. Проанализируем, как использовать метод Загрузить(). Мы выгрузим пустую структуру табличной части в Таблицу Значений, заполним ее в памяти, а затем загрузим в объект целиком:


// 1. Выгружаем только структуру колонок ТЧ (передаем пустой массив)
ТаблицаДляЗагрузки = Объект.ТаблицаЗвонков.Выгрузить(Новый Массив); 

// 2. Заполняем таблицу значений в памяти
Для Каждого Запись Из СтруктураЗвонков Цикл
    НоваяСтрока = ТаблицаДляЗагрузки.Добавить();
    ЗаполнитьЗначенияСвойств(НоваяСтрока, Запись);
КонецЦикла;

// 3. Загружаем всю таблицу в документ одним действием
Объект.ТаблицаЗвонков.Загрузить(ТаблицаДляЗагрузки);

Архитектурные советы и лучшие практики

Разберем подробнее неочевидные нюансы при работе с JSON и объектами платформы 1С, которые помогут сделать ваш код надежным и профессиональным:

  1. Отказ от конструкции Попытка... Исключение при проверке ключей. Использование исключений для управления логикой программы (проверки наличия ключа callDetails) — это антипаттерн. Вызов исключения является ресурсоемкой операцией. Гораздо быстрее и правильнее использовать метод Свойство(), как было показано в коде выше.
  2. Очистка табличной части. Перед запуском цикла обхода JSON-массива используйте метод Очистить() для табличной части (Объект.ТаблицаЗвонков.Очистить()). Это защитит от дублирования строк при повторном нажатии пользователем кнопки запроса.
  3. Функция восстановления при чтении JSON. В методе парсинга (например, ПрочитатьJSON) второй параметр часто оставляют пустым (Неопределено). Этот параметр предназначен для имени функции восстановления. В ней вы можете "на лету" преобразовывать ключи. Если API возвращает call_duration, а вам нужно Длительность, функция восстановления может переименовать ключи или преобразовать формат дат (Unix Timestamp в тип Дата) еще до того, как данные попадут в ваш основной алгоритм.
  4. Контроль типов данных. Метод ЗаполнитьЗначенияСвойств копирует данные "как есть". Если сторонний сервис вернет число как строку (например, "120"), а ваша колонка имеет строгий тип Число, значение может не установиться. Всегда контролируйте приведение базовых типов при работе со внешними API.
← На главную