Сериализация структур в 1С:Предприятие — это процесс преобразования сложных данных (таких как Структура, Массив или Соответствие) в формат, пригодный для хранения или передачи. Без этого механизма невозможно организовать обмен данными между системами, сохранить состояние объекта в файл или передать его по сети. Однако встроенные инструменты платформы 1С имеют ограничения, а неправильный подход чреват потерями данных, ошибками при десериализации или проблемами с производительностью.
В этой статье разберём все актуальные способы сериализации структур — от стандартного ЗаписатьJSON() до двоичных форматов и внешних библиотек. Особое внимание уделим типичным ошибкам при работе с вложенными объектами и рекурсивными ссылками, которые часто становятся причиной падений системы. Также покажем, как оптимизировать процесс для больших объёмов данных и интеграции с внешними сервисами.
Зачем нужна сериализация структур в 1С?
Основные сценарии, где без сериализации не обойтись:
- 📤 Обмен данными между базами 1С (включая распределённые информационные системы).
- 💾 Сохранение состояния между сеансами (например, настройки пользователя или промежуточные результаты длительных операций).
- 🌐 Интеграция с внешними системами (REST API, веб-сервисы, микросервисы).
- 🔄 Кэширование часто используемых данных для ускорения работы.
- 📊 Логирование сложных объектов для отладки или аудита.
Без сериализации при передаче структуры по сети вы получите ошибку Недопустимый тип данных, а попытка сохранить её в файл приведёт к потере иерархии. Например, структура с вложенными массивами и значениями разных типов (Число, Строка, Дата) при неверной сериализации может превратиться в бессмысленный набор символов.
⚠️ Внимание: В версиях 1С:Предприятие 8.3.10 и ниже метод ЗаписатьJSON() не поддерживает рекурсивные ссылки (например, когда структура ссылается сама на себя через вложенный элемент). Это приводит к зацикливанию и падению системы.
Стандартные методы сериализации: JSON и XML
Платформа 1С предоставляет встроенные функции для работы с наиболее популярными форматами:
- 📄
ЗаписатьJSON()/ПрочитатьJSON()— для обмена с веб-сервисами. - 📜
ЗаписатьXML()/ПрочитатьXML()— для совместимости со старыми системами.
Пример сериализации структуры в JSON:
СтруктураДанных = Новый Структура();
СтруктураДанных.Вставить("Имя", "Иван Петров");
СтруктураДанных.Вставить("Возраст", 30);
СтруктураДанных.Вставить("ДатаРождения", '1993-05-15');
JSONСтрока = ЗаписатьJSON(СтруктураДанных);
// Результат: {"Имя":"Иван Петров","Возраст":30,"ДатаРождения":"1993-05-15T00:00:00"}
Для XML синтаксис аналогичен, но результат будет выглядеть иначе:
XMLСтрока = ЗаписатьXML(СтруктураДанных);
// Результат:
// <Документ>
// <Имя>Иван Петров</Имя>
// <Возраст>30</Возраст>
// <ДатаРождения>1993-05-15T00:00:00</ДатаРождения>
// </Документ>
| Формат | Плюсы | Минусы | Когда использовать |
|---|---|---|---|
JSON |
Компактность, поддержка большинством систем, простота парсинга | Нет поддержки двоичных данных, проблемы с кодировкой | REST API, современные веб-сервисы |
XML |
Стандартизирован, поддерживает схемы валидации (XSD) | Избыточность, медленнее парсится | Старые системы, SOAP-сервисы |
Двоичный |
Максимальная скорость, минимальный размер | Нечитаемый формат, сложности с совместимостью | Внутренний обмен между базами 1С |
Проблемы со вложенными объектами и рекурсией
Одна из самых распространённых ошибок — попытка сериализовать структуру, содержащую вложенные объекты (например, другой Структура, Массив или Соответствие). В этом случае стандартные методы могут выдать ошибку или создать некорректный результат.
Пример проблемной структуры:
Данные = Новый Структура();
Данные.Вставить("Клиент", Новый Структура("ФИО, Адрес"));
Данные.Клиент.ФИО = "Петров Иван";
Данные.Клиент.Адрес = Новый Структура("Город, Улица");
Данные.Клиент.Адрес.Город = "Москва";
// П попытке сериализации в JSON получим ошибку:
// {ОписаниеОшибки: "Недопустимый тип данных для значения свойства 'Клиент'"}
Решение — использовать рекурсивную обработку или внешние библиотеки (например, 1Script.JSON). Альтернатива — преобразовать вложенные структуры в строки или массивы простых типов:
// Преобразуем вложенную структуру в строку JSON вручную
АдресJSON = ЗаписатьJSON(Данные.Клиент.Адрес);
Данные.Клиент.Адрес = АдресJSON;
⚠️ Внимание: Если структура содержитДвоичныеДанныеили объекты 1С (например,СправочникСсылка), их необходимо предварительно преобразовать в строки или базовые типы. Иначе сериализация завершится ошибкой.
Что будет, если сериализовать структуру с рекурсивной ссылкой?
При попытке сериализовать структуру, которая прямо или косвенно ссылается сама на себя (например, А.В = Б; Б.С = А;), стандартные методы 1С уйдут в бесконечную рекурсию. Это приведёт к переполнению стека и аварийному завершению сеанса. Внешние библиотеки (например, Newtonsoft.Json через COM) умеют обрабатывать такие случаи, но требуют дополнительной настройки.
Двоичная сериализация: скорость vs. совместимость
Для внутреннего обмена между базами 1С оптимален двоичный формат. Он обеспечивает:
- ⚡ Максимальную скорость (в 3–5 раз быстрее JSON/XML).
- 🗜️ Минимальный размер (нет избыточных меток, как в XML).
- 🔒 Поддержку всех типов данных 1С (включая
ДвоичныеДанныеи ссылки на объекты).
Пример записи структуры в двоичный файл:
ЗаписьДвоичныхДанных = Новый ЗаписьДанных(ИмяФайла, РежимЗаписиДанных.Дозапись);
ЗаписатьДвоичныеДанные(ЗаписьДвоичныхДанных, СтруктураДанных);
ЗаписьДвоичныхДанных.Закрыть();
Для чтения используйте ПрочитатьДвоичныеДанные(). Однако у этого метода есть критические ограничения:
- 🚫 Несовместимость между версиями 1С (файл, записанный в 8.3.20, может не прочитаться в 8.3.15).
- 🔐 Невозможность редактирования без десериализации (файл нечитаем для человека).
- 🔄 Проблемы с миграцией при изменении структуры данных.
Проверьте совместимость версий 1С на отправляющей и принимающей стороне
Убедитесь, что все объекты поддерживают сериализацию (нет ссылок на временные данные)
Зарезервируйте место для версии формата (на случай будущих изменений)
Создайте резервную копию данных перед массовой обработкой-->
Внешние библиотеки: когда стандартных методов недостаточно
Если вам нужна поддержка сложных объектов, пользовательских типов или оптимизация производительности, стоит рассмотреть внешние решения:
| Библиотека | Преимущества | Недостатки | Способ подключения |
|---|---|---|---|
| 1Script.JSON | Поддержка рекурсии, расширенные настройки форматирования | Требует установки расширения | Через ПодключитьВнешнююКомпоненту() |
| Newtonsoft.Json (через COM) | Гибкая настройка, обработка любых объектов | Сложность интеграции, зависимость от Windows | Регистрация DLL + СОМОбъект() |
| FastReport JSON | Высокая скорость, поддержка больших файлов | Платная лицензия | Внешняя компонента |
Пример использования 1Script.JSON:
ПодключитьВнешнююКомпоненту("Path\To\1Script.JSON.dll");
JSON = Новый JSONЗапись();
Результат = JSON.Сериализовать(СтруктураДанных, Истина); // Второй параметр - форматировать
⚠️ Внимание: При использовании COM-объектов (например, Newtonsoft.Json) убедитесь, что на сервере 1С разрешено выполнение внешних компонент. В противном случае получите ошибку Отказано в доступе.
Для отладки сериализации больших структур используйте инструмент Postman или 1С:Отчётность. Они позволяют визуализировать JSON/XML и быстро находить ошибки форматирования.
Оптимизация производительности при работе с большими данными
Сериализация крупных структур (например, с тысячами элементов) может занимать значительное время и нагружать сервер. Чтобы ускорить процесс:
- ⏱️ Используйте потоковую запись (не формируйте всю строку JSON/XML в памяти).
- 🗃️ Разбивайте данные на части (пакетная обработка).
- 🔧 Отключайте форматирование (параметр
Форматировать = ЛожьвЗаписатьJSON()). - 📉 Избегайте вложенных структур (преобразуйте их в плоские массивы).
Пример потоковой записи JSON:
ЗаписьТекста = Новый ЗаписьТекста(ИмяФайла);
ЗаписьJSON = Новый ЗаписьJSON(ЗаписьТекста);
ЗаписьJSON.ЗаписатьНачалоОбъекта();
ЗаписьJSON.ЗаписатьИмяСвойства("Данные");
ЗаписьJSON.ЗаписатьНачалоМассива();
Для Каждого Элемент Из БольшойМассив Цикл
ЗаписьJSON.ЗаписатьЗначение(Элемент);
КонецЦикла;
ЗаписьJSON.ЗаписатьКонецМассива();
ЗаписьJSON.ЗаписатьКонецОбъекта();
ЗаписьТекста.Закрыть();
Для двоичных данных используйте ПотокВПамяти или ФайловыйПоток, чтобы избежать переполнения памяти:
Поток = Новый ПотокВПамяти();
ЗаписьДвоичныхДанных = Новый ЗаписьДанных(Поток);
ЗаписатьДвоичныеДанные(ЗаписьДвоичныхДанных, БольшаяСтруктура);
ДвоичныеДанные = Поток.ЗакрытьИПолучитьДанные();
При работе с данными объёмом более 100 МБ обязательно используйте потоковую обработку. Иначе рискуете получить ошибку Недостаточно памяти или блокировку интерфейса.
Типичные ошибки и как их избежать
Даже опытные разработчики сталкиваются с проблемами при сериализации. Вот наиболее частые из них:
- Потеря типов данных:
При чтении JSON строка
"123"может стать числом123, а дата — строкой. Всегда проверяйте типы после десериализации:Если ТипЗнч(ПрочитанноеЗначение) = Тип("Строка") И ЗначениеЗаполнено(ПрочитанноеЗначение) ТогдаПопытка
ПрочитанноеЗначение = Число(ПрочитанноеЗначение);
Исключение
// Обработка ошибки преобразования
КонецПопытки;
КонецЕсли;
- Кодировка символов:
При записи в файл укажите явную кодировку (например,
КодировкаТекста.UTF8), иначе русские символы превратятся в????. - Циклические ссылки:
Если структура A содержит ссылку на структуру B, а структура B — обратно на A, стандартная сериализация зациклится. Используйте внешние библиотеки с поддержкой
ReferenceLoopHandling. - Ограничения на размер:
В веб-сервисах 1С максимальный размер JSON-сообщения по умолчанию — 10 МБ. Для больших данных настройте параметр
МаксимальныйРазмерПакетав конфигурации.
Для проверки корректности сериализации используйте валидаторы:
- 🔍 JSONLint — для валидации JSON.
- 📋 XMLValidation — для проверки XML.
FAQ: Ответы на частые вопросы
Как сериализовать структуру с объектами 1С (например, СправочникСсылка)?
Объекты 1С (справочники, документы) нельзя сериализовать напрямую. Преобразуйте их в строки или структуры с базовыми типами:
Данные = Новый Структура();
Данные.Вставить("Контрагент", Справочник.Контрагенты.Наименование); // Вместо ссылки - наименование
// Или:
Данные.Вставить("КонтрагентID", Справочник.Контрагенты.УникальныйИдентификатор());
Можно ли сериализовать структуру с двоичными данными в JSON?
Нет, ЗаписатьJSON() не поддерживает ДвоичныеДанные. Преобразуйте их в Base64:
ДвоичныеДанные = ПолучаемДвоичныеДанные();
СтрокаBase64 = Base64Строка(ДвоичныеДанные);
Структура.Вставить("Файл", СтрокаBase64);
Как ускорить сериализацию массива из 100 000 элементов?
Используйте потоковую запись и отключите форматирование:
ПараметрыJSON = Новый ПараметрыЗаписиJSON();
ПараметрыJSON.УстановитьСтрогийРежимИменСвойств(Истина);
ПараметрыJSON.Форматировать = Ложь;
JSONСтрока = ЗаписатьJSON(БольшойМассив, ПараметрыJSON);
Также рассмотрите разбиение массива на пакеты по 10 000 элементов.
Что делать, если после десериализации даты становятся строками?
Явно преобразуйте строки обратно в даты:
Если ТипЗнч(ПрочитаннаяДата) = Тип("Строка") Тогда
ПрочитаннаяДата = Дата(ПрочитаннаяДата);
КонецЕсли;
Или настройте параметры чтения JSON:
ПараметрыJSON = Новый ПараметрыЧтенияJSON();
ПараметрыJSON.ПреобразовыватьДатаВремяИзСтроки = Истина;
Как сериализовать структуру с рекурсивными ссылками?
Стандартными средствами — никак. Используйте внешние библиотеки (например, Newtonsoft.Json) с настройкой:
// Псевдокод для COM-объекта
JSONSettings = Новый JSONSerializerSettings();
JSONSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
JSON = JSONConvert.SerializeObject(Структура, JSONSettings);