При обмене данными между различными системами или при сохранении сложных настроек в файлах часто возникает необходимость преобразования структур данных 1С в универсальный текстовый формат, такой как JSON. Рассмотрим подробно, как выполнить сериализацию структуры, содержащей поля различных типов – дату, строку, булево, число и массив чисел – в JSON и обратно в системе 1С:Предприятие.
Для работы с JSON в 1С мы используем стандартные объекты платформы: ЗаписьJSON и ЧтениеJSON, а также глобальные методы ЗаписатьJSON() и ПрочитатьJSON(). Эти инструменты позволяют нам гибко управлять процессом преобразования данных. Для разбора сложных иерархических ответов можно использовать готовое решение для загрузки данных из JSON в дерево значений.
Платформа 1С, начиная с версии 8.3.6, предоставляет низкоуровневые инструменты для работы с JSON. Чтобы сериализовать структуру в строку JSON, мы выполняем следующие шаги:
ЗаписьJSON. Этот объект является потоком для записи данных в JSON-формате.ПараметрыЗаписиJSON. Он позволяет нам настраивать формат вывода JSON (например, отступы, переносы строк).ЗаписьJSON с помощью метода УстановитьСтроку(), передавая ему параметры записи. Это означает, что JSON будет записан в строковую переменную в памяти.ЗаписатьJSON(). Ему передаются два параметра: наш объект ЗаписьJSON и структура данных, которую мы хотим сериализовать. Этот метод автоматически преобразует структуру 1С в объект JSON.Закрыть() объекта ЗаписьJSON, который возвращает нам итоговую строку JSON.Давайте посмотрим на пример функции, которая выполняет сериализацию любой структуры данных в строку JSON:
// Функция для сериализации любых данных в строку JSON
// Параметры:
// Данные - Произвольные данные (Структура, Массив, ПримитивныеТипы)
// Возвращаемое значение:
// Строка - Строка JSON, представляющая исходные данные
Функция СтрокаJSON(Данные) Экспорт
ЗаписьJSON = Новый ЗаписьJSON;
// Можно настроить параметры записи для форматирования JSON
ПараметрыJSON = Новый ПараметрыЗаписиJSON;
ПараметрыJSON.УстановитьИспользованиеДвойныхКавычекДляКлючей(Истина);
ПараметрыJSON.УстановитьПереносСтрок(ПереносСтрокJSON.Авто);
ПараметрыJSON.УстановитьСимволыОтступа(Символы.Таб);
ЗаписьJSON.УстановитьСтроку(ПараметрыJSON);
ЗаписатьJSON(ЗаписьJSON, Данные);
Возврат ЗаписьJSON.Закрыть();
КонецФункции
Теперь давайте создадим пример структуры с различными типами полей, о которых шла речь в исходном вопросе, и сериализуем ее:
// Создаем структуру с полями разных типов
СтруктураДанных = Новый Структура;
СтруктураДанных.Вставить("Имя", "Тестовая запись"); // Строка
СтруктураДанных.Вставить("Количество", 123.45); // Число
СтруктураДанных.Вставить("Активно", Истина); // Булево
СтруктураДанных.Вставить("ДатаСоздания", ТекущаяДата()); // Дата
СтруктураДанных.Вставить("МассивЧисел", Новый Массив); // Массив чисел
СтруктураДанных.МассивЧисел.Добавить(1);
СтруктураДанных.МассивЧисел.Добавить(2.5);
СтруктураДанных.МассивЧисел.Добавить(3);
// Сериализуем структуру в JSON
СтрокаJSON = СтрокаJSON(СтруктураДанных);
Сообщить("Сериализованная строка JSON:");
Сообщить(СтрокаJSON);
Как мы видим, основные типы данных 1С (строка, число, булево, массив, структура) прекрасно преобразуются в их JSON-эквиваленты. Особое внимание следует уделить работе с датами.
Сериализация значений типа Дата по умолчанию выполняется в формате ISO (например, "2009-02-15T00:00:00Z"). Этот формат является общепринятым, но важно помнить, что стандарт JSON сам по себе не определяет единый формат для представления дат. Вид представления даты может быть важен для принимающей системы.
При записи данных через ЗаписатьJSON() управление форматом даты не всегда очевидно. Однако, мы можем использовать объект ПараметрыЗаписиJSON и его свойство НастройкиСериализацииJSON для тонкой настройки. Например, мы можем явно указать формат даты, используя перечисление ФорматДатыJSON:
// Пример использования ПараметрыЗаписиJSON для настройки формата даты
Функция СтрокаJSONСНастройкойДаты(Данные) Экспорт
ЗаписьJSON = Новый ЗаписьJSON;
ПараметрыJSON = Новый ПараметрыЗаписиJSON;
// Устанавливаем ISO формат даты, если он не установлен по умолчанию или хотим быть явными
ПараметрыJSON.УстановитьФорматДаты(ФорматДатыJSON.ISO);
// Также можно задать другие параметры форматирования
ПараметрыJSON.УстановитьПереносСтрок(ПереносСтрокJSON.Авто);
ПараметрыJSON.УстановитьСимволыОтступа(Символы.Пробел, 2);
ЗаписьJSON.УстановитьСтроку(ПараметрыJSON);
ЗаписатьJSON(ЗаписьJSON, Данные);
Возврат ЗаписьJSON.Закрыть();
КонецФункции
Платформа 1С:Предприятие поддерживает несколько форматов представления даты, задаваемых с помощью системного перечисления ФорматДатыJSON. Изучите его для выбора наиболее подходящего формата.
Для обратного преобразования из строки JSON в данные 1С используется объект ЧтениеJSON и глобальный метод ПрочитатьJSON(). Процесс десериализации выглядит следующим образом:
ЧтениеJSON.УстановитьСтроку().ПрочитатьJSON(), передавая ему объект ЧтениеJSON. Этот метод возвращает нам данные, прочитанные из JSON, автоматически преобразуя их в стандартные типы 1С: Строка, Число, Булево, Неопределено, Массив, Структура, Соответствие, Дата (при правильном распознавании).Закрыть() объекта ЧтениеJSON.Рассмотрим функцию для десериализации:
// Функция для десериализации строки JSON в данные 1С
// Параметры:
// СтрокаJSON - Строка JSON
// Возвращаемое значение:
// Произвольные данные (Структура, Массив, ПримитивныеТипы)
Функция ДанныеИзСтрокиJSON(СтрокаJSON) Экспорт
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(СтрокаJSON);
Данные = ПрочитатьJSON(ЧтениеJSON);
ЧтениеJSON.Закрыть();
Возврат Данные;
КонецФункции
И пример использования с нашей ранее сериализованной строкой:
// Десериализуем строку JSON обратно в структуру 1С
ИсходнаяСтрокаJSON = СтрокаJSON(СтруктураДанных); // Получаем строку из предыдущего примера
ВосстановленнаяСтруктура = ДанныеИзСтрокиJSON(ИсходнаяСтрокаJSON);
Сообщить("Восстановленная структура:");
Для Каждого КлючЗначение Из ВосстановленнаяСтруктура Цикл
Сообщить(" " + КлючЗначение.Ключ + ": " + Строка(КлючЗначение.Значение) + " (Тип: " + ТипЗнч(КлючЗначение.Значение) + ")");
КонецЦикла;
// Пример доступа к полю
Сообщить("Имя из восстановленной структуры: " + ВосстановленнаяСтруктура.Имя);
Сообщить("Активно из восстановленной структуры: " + ВосстановленнаяСтруктура.Активно);
Основная сложность при десериализации данных из JSON заключается в распознавании полей типа Дата. Метод ПрочитатьJSON() не всегда автоматически распознает строковые представления дат и может интерпретировать их просто как строки. Для универсальной десериализации дат может потребоваться дополнительная обработка восстановленных данных. Например, можно проверять тип каждого поля и, если это строка, которая соответствует формату даты, преобразовывать ее в тип Дата вручную.
Один из подходов – передавать в функцию десериализации "словарь" или "карту" полей, которые должны быть датами. После стандартной десериализации мы можем пройтись по этим полям и преобразовать их:
// Функция для десериализации строки JSON с учетом специфичных полей-дат
Функция ДанныеИзСтрокиJSONСПреобразованиемДат(СтрокаJSON, КартаПолейДат = Неопределено) Экспорт
Данные = ДанныеИзСтрокиJSON(СтрокаJSON); // Используем нашу базовую функцию десериализации
Если ТипЗнч(Данные) = Тип("Структура") И КартаПолейДат <> Неопределено Тогда
Для Каждого ИмяПоляДаты Из КартаПолейДат Цикл
Если Данные.Свойство(ИмяПоляДаты) И ТипЗнч(Данные[ИмяПоляДаты]) = Тип("Строка") Тогда
Попытка
// Пытаемся преобразовать строку в дату.
// Важно, чтобы строка была в одном из форматов, понятных 1С.
Данные[ИмяПоляДаты] = Дата(Данные[ИмяПоляДаты]);
Исключение
// Обработка ошибки, если строка не является корректной датой
Сообщить("Ошибка преобразования поля '" + ИмяПоляДаты + "' в дату: " + ОписаниеОшибки(), СтатусСообщения.Важное);
КонецПопытки;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Возврат Данные;
КонецФункции
// Пример использования с картой полей-дат
КартаДат = Новый Массив;
КартаДат.Добавить("ДатаСоздания");
ВосстановленнаяСтруктураСДатами = ДанныеИзСтрокиJSONСПреобразованиемДат(ИсходнаяСтрокаJSON, КартаДат);
Сообщить("Восстановленная структура с преобразованными датами:");
Для Каждого КлючЗначение Из ВосстановленнаяСтруктураСДатами Цикл
Сообщить(" " + КлючЗначение.Ключ + ": " + Строка(КлючЗначение.Значение) + " (Тип: " + ТипЗнч(КлючЗначение.Значение) + ")");
КонецЦикла;
Такой подход обеспечивает большую надежность при работе с датами, полученными из внешних систем.
Объект ПараметрыЗаписиJSON позволяет нам контролировать внешний вид генерируемой строки JSON. Мы уже видели примеры использования для переносов строк и отступов. Рассмотрим подробнее доступные параметры:
УстановитьПереносСтрок(ПереносСтрокJSON): Определяет, будут ли в JSON присутствовать переносы строк для лучшей читаемости. Возможные значения: ПереносСтрокJSON.Нет, ПереносСтрокJSON.Авто.УстановитьСимволыОтступа(Строка, Количество = 0): Задает символы, используемые для отступов (например, Символы.Таб или Символы.Пробел) и их количество. Это делает JSON более наглядным.УстановитьИспользованиеДвойныхКавычекДляКлючей(Булево): Управляет тем, будут ли ключи JSON-объектов заключаться в двойные кавычки. Согласно стандарту JSON, ключи всегда должны быть строками в двойных кавычках, поэтому рекомендуется устанавливать Истина.УстановитьИспользованиеЭкранированияСимволов(Булево): Определяет, будут ли специальные символы (например, кавычки, обратный слэш) экранироваться при записи.УстановитьПроверкуКорректности(Булево): Включает или отключает проверку правильности записываемой структуры JSON. Отключение может немного увеличить скорость для больших объемов данных, но рекомендуется использовать только для проверенных структур.УстановитьФорматДаты(ФорматДатыJSON): Как мы уже обсуждали, позволяет явно задать формат, в котором будут сериализоваться значения типа Дата.Эти параметры дают нам полный контроль над форматированием JSON, что особенно полезно при взаимодействии с внешними системами, предъявляющими строгие требования к формату данных.
Начиная с версии 8.3.7.1759, платформа 1С предоставляет более мощный механизм для сериализации в JSON – XDTO-сериализацию. Она предназначена для сериализации прикладных типов 1С, таких как ссылки на объекты, сами объекты конфигурации, наборы записей и любые типы, для которых поддерживается XDTO-сериализация. Этот метод часто рекомендуется для обмена данными между двумя приложениями 1С:Предприятия, поскольку он более компактен и быстрее выполняется по сравнению с обычным XML-обменом.
Для XDTO-сериализации используется объект СериализаторXDTO:
ФабрикаXDTO, которая служит для создания типов XDTO и объектов.СериализаторXDTO, передавая ему фабрику XDTO.СериализаторXDTO.ЗаписатьJSON() и СериализаторXDTO.ПрочитатьJSON().Рассмотрим пример XDTO-сериализации:
// Пример XDTO-сериализации прикладного объекта 1С
// Предположим, у нас есть ссылка на элемент справочника "Номенклатура"
Функция СериализоватьОбъектXDTOВJSON(СсылкаНаОбъект) Экспорт
Если СсылкаНаОбъект = Неопределено Или СсылкаНаОбъект = Null Тогда
Возврат "";
КонецЕсли;
ФабрикаXDTO = Новый ФабрикаXDTO;
СериализаторXDTO = Новый СериализаторXDTO(ФабрикаXDTO);
ЗаписьJSON = Новый ЗаписьJSON;
ПараметрыJSON = Новый ПараметрыЗаписиJSON;
ПараметрыJSON.УстановитьПереносСтрок(ПереносСтрокJSON.Авто);
ПараметрыJSON.УстановитьСимволыОтступа(Символы.Пробел, 2);
ЗаписьJSON.УстановитьСтроку(ПараметрыJSON);
СериализаторXDTO.ЗаписатьJSON(ЗаписьJSON, СсылкаНаОбъект);
Возврат ЗаписьJSON.Закрыть();
КонецФункции
Функция ДесериализоватьОбъектXDTOИзJSON(СтрокаJSON, ТипЗначения = Неопределено) Экспорт
Если СтрокаJSON = "" Тогда
Возврат Неопределено;
КонецЕсли;
ФабрикаXDTO = Новый ФабрикаXDTO;
СериализаторXDTO = Новый СериализаторXDTO(ФабрикаXDTO);
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(СтрокаJSON);
Если ТипЗначения = Неопределено Тогда
// Десериализация без указания типа
Возврат СериализаторXDTO.ПрочитатьJSON(ЧтениеJSON);
Иначе
// Десериализация с указанием типа (например, Тип("СправочникСсылка.Номенклатура"))
Возврат СериализаторXDTO.ПрочитатьJSON(ЧтениеJSON, ТипЗначения);
КонецЕсли;
КонецФункции
// Пример использования (требует наличия справочника "Номенклатура")
// ПопыткаПолучитьСсылку = Справочники.Номенклатура.НайтиПоНаименованию("Какой-то товар"); // Замените на реальное наименование
// Если ПопыткаПолучитьСсылку <> Неопределено Тогда
// СериализованныйОбъект = СериализоватьОбъектXDTOВJSON(ПопыткаПолучитьСсылку);
// Сообщить("XDTO Сериализованный объект: " + СериализованныйОбъект);
//
// ВосстановленнаяСсылка = ДесериализоватьОбъектXDTOИзJSON(СериализованныйОбъект, Тип("СправочникСсылка.Номенклатура"));
// Сообщить("XDTO Восстановленная ссылка: " + ВосстановленнаяСсылка);
// КонецЕсли;
Важно отметить, что XDTO-сериализация в JSON наиболее эффективна, когда необходимо передать между системами 1С именно прикладные объекты (ссылки, документы, элементы справочников), а не просто универсальные структуры. При десериализации с помощью СериализаторXDTO.ПрочитатьJSON() можно указать ожидаемый тип значения, что улучшает точность восстановления данных.
При десериализации с использованием XDTO также есть возможность изменить получаемые данные с помощью функции восстановления, которую можно передать в метод ПрочитатьJSON(). Это позволяет реализовать сложную логику преобразования данных "на лету" в процессе десериализации.
Мы рассмотрели различные аспекты сериализации и десериализации структур данных в JSON в 1С. Для простых структур с примитивными типами данных и массивами, а также для универсального обмена, лучше подходят глобальные методы ЗаписатьJSON() и ПрочитатьJSON(). В случае работы с датами, обращайте внимание на их формат и при необходимости используйте дополнительные преобразования при десериализации. Для обмена прикладными объектами 1С между информационными базами более эффективным может быть использование XDTO-сериализации через СериализаторXDTO.
Правильный выбор метода и внимательное отношение к типам данных, особенно к датам, обеспечат надежный и эффективный обмен информацией в ваших решениях на платформе 1С:Предприятие.