Как быстро выгрузить результат запроса 1С в JSON или XML без перебора отдельных записей?

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

Когда мы разрабатываем веб-сервисы в 1С:Предприятии, часто возникает задача быстро выгрузить результаты запроса в форматы JSON или XML. Изначально может показаться, что объект РезультатЗапроса, который возвращается методом Запрос.Выполнить(), можно напрямую сериализовать в нужный формат. Однако, как показывает практика и обсуждения, в платформе 1С есть свои нюансы, и прямая сериализация РезультатаЗапроса в XML или JSON через стандартные механизмы СериализаторXDTO не поддерживается. Давайте разберем эту проблему и рассмотрим эффективные способы ее решения.

Почему прямая сериализация РезультатаЗапроса не работает?

В платформе 1С объект РезультатЗапроса предназначен для последовательного доступа к данным. Это означает, что он действует как курсор, позволяя нам перебирать записи одну за другой, но не хранит весь набор данных целиком в оперативной памяти как готовую структуру для моментальной сериализации. Хотя документация 1С может указывать, что РезультатЗапроса "сериализуется", это не означает, что он может быть напрямую передан в СериализаторXDTO для получения стандартного XML или JSON.

Если мы попытаемся использовать метод ЗначениеВСтрокуВнутр() для объекта РезультатЗапроса, мы действительно получим строковое представление. Однако это будет внутренний формат платформы 1С, который совершенно не похож на стандартный XML или JSON и не предназначен для обмена данными с внешними системами. Рассмотрим пример:


З = Новый Запрос("ВЫБРАТЬ * ИЗ Справочник.Валюты");
Р = З.Выполнить();
Сообщить(ЗначениеВСтрокуВнутр(Р));

В результате такого вызова мы увидим сложную, трудночитаемую структуру, которая не является ни XML, ни JSON.

Более того, прямая попытка сериализовать РезультатЗапроса через СериализаторXDTO приведет к ошибкам. Например, код:


З = Новый Запрос("ВЫБРАТЬ * ИЗ Справочник.Валюты");
Р = З.Выполнить();
ЗаписьXML = Новый ЗаписьXML();
ЗаписьXML.УстановитьСтроку();
СериализаторXDTO.ЗаписатьXML(ЗаписьXML, Р);
СтрокаXML = ЗаписьXML.Закрыть();
Сообщить(СтрокаXML);

вызовет ошибку типа "Несоответствие типов" или "Значения данного типа не могут быть представлены в XML". Это подтверждает, что РезультатЗапроса не имеет стандартного XDTO-типа, который мог бы быть использован для прямой сериализации.

Решение 1: Сериализация ТаблицыЗначений

Самый распространенный и рабочий способ получить XML или JSON из результатов запроса в 1С без написания сложного ручного кода – это предварительная выгрузка РезультатаЗапроса в объект ТаблицаЗначений. Объект ТаблицаЗначений является сериализуемым и имеет соответствующий XDTO-тип (ValueTable в пространстве имен {http://v8.1c.ru/8.1/data/core}), что позволяет успешно использовать СериализаторXDTO.

Разберем по шагам, как это сделать:

  1. Выполняем запрос: Сначала мы создаем объект Запрос и выполняем его, получая РезультатЗапроса.

  2. Выгружаем в ТаблицуЗначений: Затем используем метод Выгрузить(), который преобразует РезультатЗапроса в ТаблицуЗначений. Важно понимать, что этот шаг по своей сути является перебором записей, но выполняется он внутренними средствами платформы 1С, что обычно гораздо быстрее и эффективнее, чем ручной перебор в коде на 1С.

    
    З = Новый Запрос("ВЫБРАТЬ * ИЗ Справочник.Валюты");
    Р = З.Выполнить().Выгрузить(); // Здесь происходит выгрузка в ТаблицуЗначений
    
  3. Сериализуем ТаблицуЗначений в XML: После получения ТаблицыЗначений мы можем легко сериализовать ее в XML, используя объекты ЗаписьXML и СериализаторXDTO.

    
    ЗаписьXML = Новый ЗаписьXML();
    ЗаписьXML.УстановитьСтроку();
    СериализаторXDTO.ЗаписатьXML(ЗаписьXML, Р); // Р теперь это ТаблицаЗначений
    СтрокаXML = ЗаписьXML.Закрыть();
    Сообщить(СтрокаXML);
    

    В результате мы получим структурированный XML-файл, где будут представлены метаданные таблицы (описание колонок) и данные построчно. Формат будет соответствовать XDTO-схеме для ValueTable.

  4. Сериализуем ТаблицуЗначений в JSON: Аналогично, мы можем получить JSON-представление. Для этого используем ЗаписьJSON и СериализаторXDTO.ЗаписатьJSON(). Параметр НазначениеТипаXML.Явное указывает сериализатору явно указывать типы данных в JSON.

    
    З = Новый Запрос("ВЫБРАТЬ * ИЗ Справочник.Валюты");
    Р = З.Выполнить().Выгрузить();
    ЗаписьJSON = Новый ЗаписьJSON;
    ЗаписьJSON.УстановитьСтроку();
    СериализаторXDTO.ЗаписатьJSON(ЗаписьJSON, Р, НазначениеТипаXML.Явное);
    СтрокаJSON = ЗаписьJSON.Закрыть();
    Сообщить(СтрокаJSON);
    

    Этот подход позволяет получить JSON-структуру, которая также будет содержать описание колонок и массивы значений для каждой строки, с указанием типов данных. Хотя формат может быть немного многословным из-за метаинформации, он является стандартным и легко парсится.

Плюсы и минусы решения с ТаблицейЗначений:

Решение 2: Ручное формирование JSON/XML через Выборку (для больших объемов или специфичного формата)

Если объемы данных критичны или требуется строго определенный формат JSON/XML, который не может быть получен стандартной сериализацией ТаблицыЗначений, мы вынуждены прибегнуть к ручному формированию. В этом случае мы будем использовать ВыборкуИзРезультатаЗапроса, которая позволяет последовательно обрабатывать данные, не загружая их все в память одновременно.

Разберем, как это реализовать:

  1. Получаем ВыборкуИзРезультатаЗапроса: Вместо Выполнить().Выгрузить(), мы используем Выполнить().Выбрать(). Это возвращает нам объект ВыборкаИзРезультатаЗапроса, который по сути является курсором по данным.

  2. Инициализируем объекты для записи: Мы создаем объекты ЗаписьJSON или ЗаписьXML для пошаговой записи элементов.

  3. Перебираем выборку и формируем структуру: В цикле по выборке мы вручную пишем нужные элементы и атрибуты, создавая желаемую структуру JSON или XML.

Пример ручного формирования JSON:

Предположим, нам нужен простой JSON-массив объектов, где каждый объект – это товар со свойствами "Код" и "Наименование".


З = Новый Запрос("ВЫБРАТЬ Код, Наименование ИЗ Справочник.Валюты КАК Валюты");
Выборка = З.Выполнить().Выбрать();

ЗаписьJSON = Новый ЗаписьJSON();
ЗаписьJSON.УстановитьСтроку();
ЗаписьJSON.НачатьЗаписьМассива(); // Начинаем запись JSON-массива

Пока Выборка.Следующий() Цикл
    ЗаписьJSON.НачатьЗаписьОбъекта(); // Начинаем запись объекта для текущей строки
    
    ЗаписьJSON.ЗаписатьИмя("Код");
    ЗаписьJSON.ЗаписатьЗначение(Выборка.Код);
    
    ЗаписьJSON.ЗаписатьИмя("Наименование");
    ЗаписьJSON.ЗаписатьЗначение(Выборка.Наименование);
    
    ЗаписьJSON.ЗакончитьЗаписьОбъекта(); // Заканчиваем запись объекта
КонецЦикла;

ЗаписьJSON.ЗакончитьЗаписьМассива(); // Заканчиваем запись JSON-массива
СтрокаJSON = ЗаписьJSON.Закрыть();
Сообщить(СтрокаJSON);

Этот код позволяет получить JSON-массив вида:


[
 { "Код": "56", "Наименование": "У.Е." },
 { "Код": "643", "Наименование": "RUB" },
 { "Код": "840", "Наименование": "USD" },
 { "Код": "978", "Наименование": "EUR" }
]

Аналогичным образом можно сформировать XML, используя ЗаписьXML и ее методы ЗаписатьНачалоЭлемента(), ЗаписатьАтрибут(), ЗаписатьТекст() и ЗаписатьКонецЭлемента().

Плюсы и минусы ручного формирования:

Решение 3: Использование OData

Для веб-сервисов, особенно если требуется не просто разовая выгрузка, а полноценный API для работы с данными, стоит рассмотреть использование стандартного интерфейса OData, который встроен в платформу 1С:Предприятие.

Что такое OData?

OData (Open Data Protocol) – это открытый протокол, разработанный Microsoft, который позволяет создавать и потреблять RESTful API. В 1С он предоставляет стандартизированный способ доступа к данным информационной базы в форматах Atom/XML или JSON, используя обычные HTTP-запросы.

Как OData решает проблему "без перебора"?

Когда мы используем OData, платформа 1С сама берет на себя задачу генерации запросов к базе данных и формирования ответа в нужном формате (JSON или XML). Разработчику не нужно писать код для выполнения запроса, выгрузки в таблицу или ручного формирования строк. Мы просто публикуем информационную базу как OData-сервис, и внешние системы могут к ней обращаться, используя стандартные URL-адреса и параметры запросов.

Преимущества OData:

Для веб-сервисов, где важна скорость и универсальность, OData является предпочтительным выбором, поскольку он делегирует сложную задачу формирования данных и их сериализации самой платформе, освобождая нас от ручной работы.

Дополнительные соображения по производительности

Независимо от выбранного способа, мы должны помнить, что на общую производительность веб-сервиса влияют и другие факторы:

Всегда рекомендуется проводить замеры производительности (профилирование) для выявления реальных узких мест в наших веб-сервисах. Возможно, тормоз не в самой выгрузке или сериализации, а в инициализации сеанса или сложности исходного запроса.

Итог

Итак, если мы стремимся быстро выгрузить результат запроса в JSON или XML, не перебирая записи "вручную" в нашем коде, у нас есть несколько рабочих вариантов:

  1. Самый простой и быстрый в реализации: Выгрузить РезультатЗапроса в ТаблицуЗначений методом Выгрузить(), а затем использовать СериализаторXDTO для получения XML или JSON. Этот метод подходит для средних объемов данных и когда стандартный XDTO-формат приемлем — есть готовый универсальный экспорт в XML и JSON.

  2. Для больших объемов или специфического формата: Использовать ВыборкуИзРезультатаЗапроса (полученную через Выбрать()) и вручную формировать JSON или XML с помощью объектов ЗаписьJSON или ЗаписьXML. Это дает полный контроль над форматом и экономит память, но требует большего объема кода.

  3. Для полноценных API: Применять OData, который позволяет платформе 1С автоматически генерировать и отдавать данные в JSON/XML, с поддержкой фильтрации, сортировки и пагинации на стороне сервера. Это самый эффективный и стандартизированный подход для сложных веб-сервисов.

В конечном итоге, выбор метода зависит от конкретных требований к формату, объему данных и общей архитектуре нашего веб-сервиса.

← На главную