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

В этой статье разберём все актуальные способы сериализации структур — от стандартного ЗаписатьJSON() до двоичных форматов и внешних библиотек. Особое внимание уделим типичным ошибкам при работе с вложенными объектами и рекурсивными ссылками, которые часто становятся причиной падений системы. Также покажем, как оптимизировать процесс для больших объёмов данных и интеграции с внешними сервисами.

Зачем нужна сериализация структур в 1С?

Основные сценарии, где без сериализации не обойтись:

  • 📤 Обмен данными между базами (включая распределённые информационные системы).
  • 💾 Сохранение состояния между сеансами (например, настройки пользователя или промежуточные результаты длительных операций).
  • 🌐 Интеграция с внешними системами (REST API, веб-сервисы, микросервисы).
  • 🔄 Кэширование часто используемых данных для ускорения работы.
  • 📊 Логирование сложных объектов для отладки или аудита.

Без сериализации при передаче структуры по сети вы получите ошибку Недопустимый тип данных, а попытка сохранить её в файл приведёт к потере иерархии. Например, структура с вложенными массивами и значениями разных типов (Число, Строка, Дата) при неверной сериализации может превратиться в бессмысленный набор символов.

⚠️ Внимание: В версиях 1С:Предприятие 8.3.10 и ниже метод ЗаписатьJSON() не поддерживает рекурсивные ссылки (например, когда структура ссылается сама на себя через вложенный элемент). Это приводит к зацикливанию и падению системы.

Стандартные методы сериализации: JSON и XML

Платформа предоставляет встроенные функции для работы с наиболее популярными форматами:

  • 📄 Записать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
XML
Двоичный
Другой

Проблемы со вложенными объектами и рекурсией

Одна из самых распространённых ошибок — попытка сериализовать структуру, содержащую вложенные объекты (например, другой Структура, Массив или Соответствие). В этом случае стандартные методы могут выдать ошибку или создать некорректный результат.

Пример проблемной структуры:

Данные = Новый Структура();

Данные.Вставить("Клиент", Новый Структура("ФИО, Адрес"));

Данные.Клиент.ФИО = "Петров Иван";

Данные.Клиент.Адрес = Новый Структура("Город, Улица");

Данные.Клиент.Адрес.Город = "Москва";

// П попытке сериализации в JSON получим ошибку:

// {ОписаниеОшибки: "Недопустимый тип данных для значения свойства 'Клиент'"}

Решение — использовать рекурсивную обработку или внешние библиотеки (например, 1Script.JSON). Альтернатива — преобразовать вложенные структуры в строки или массивы простых типов:

// Преобразуем вложенную структуру в строку JSON вручную

АдресJSON = ЗаписатьJSON(Данные.Клиент.Адрес);

Данные.Клиент.Адрес = АдресJSON;

⚠️ Внимание: Если структура содержит ДвоичныеДанные или объекты (например, СправочникСсылка), их необходимо предварительно преобразовать в строки или базовые типы. Иначе сериализация завершится ошибкой.
Что будет, если сериализовать структуру с рекурсивной ссылкой?

При попытке сериализовать структуру, которая прямо или косвенно ссылается сама на себя (например, А.В = Б; Б.С = А;), стандартные методы уйдут в бесконечную рекурсию. Это приведёт к переполнению стека и аварийному завершению сеанса. Внешние библиотеки (например, Newtonsoft.Json через COM) умеют обрабатывать такие случаи, но требуют дополнительной настройки.

Двоичная сериализация: скорость vs. совместимость

Для внутреннего обмена между базами оптимален двоичный формат. Он обеспечивает:

  • Максимальную скорость (в 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) убедитесь, что на сервере разрешено выполнение внешних компонент. В противном случае получите ошибку Отказано в доступе.
💡

Для отладки сериализации больших структур используйте инструмент Postman или 1С:Отчётность. Они позволяют визуализировать JSON/XML и быстро находить ошибки форматирования.

Оптимизация производительности при работе с большими данными

Сериализация крупных структур (например, с тысячами элементов) может занимать значительное время и нагружать сервер. Чтобы ускорить процесс:

  • ⏱️ Используйте потоковую запись (не формируйте всю строку JSON/XML в памяти).
  • 🗃️ Разбивайте данные на части (пакетная обработка).
  • 🔧 Отключайте форматирование (параметр Форматировать = Ложь в ЗаписатьJSON()).
  • 📉 Избегайте вложенных структур (преобразуйте их в плоские массивы).

Пример потоковой записи JSON:

ЗаписьТекста = Новый ЗаписьТекста(ИмяФайла);

ЗаписьJSON = Новый ЗаписьJSON(ЗаписьТекста);

ЗаписьJSON.ЗаписатьНачалоОбъекта();

ЗаписьJSON.ЗаписатьИмяСвойства("Данные");

ЗаписьJSON.ЗаписатьНачалоМассива();

Для Каждого Элемент Из БольшойМассив Цикл

ЗаписьJSON.ЗаписатьЗначение(Элемент);

КонецЦикла;

ЗаписьJSON.ЗаписатьКонецМассива();

ЗаписьJSON.ЗаписатьКонецОбъекта();

ЗаписьТекста.Закрыть();

Для двоичных данных используйте ПотокВПамяти или ФайловыйПоток, чтобы избежать переполнения памяти:

Поток = Новый ПотокВПамяти();

ЗаписьДвоичныхДанных = Новый ЗаписьДанных(Поток);

ЗаписатьДвоичныеДанные(ЗаписьДвоичныхДанных, БольшаяСтруктура);

ДвоичныеДанные = Поток.ЗакрытьИПолучитьДанные();

💡

При работе с данными объёмом более 100 МБ обязательно используйте потоковую обработку. Иначе рискуете получить ошибку Недостаточно памяти или блокировку интерфейса.

Типичные ошибки и как их избежать

Даже опытные разработчики сталкиваются с проблемами при сериализации. Вот наиболее частые из них:

  1. Потеря типов данных:

    При чтении JSON строка "123" может стать числом 123, а дата — строкой. Всегда проверяйте типы после десериализации:

    Если ТипЗнч(ПрочитанноеЗначение) = Тип("Строка") И ЗначениеЗаполнено(ПрочитанноеЗначение) Тогда
    

    Попытка

    ПрочитанноеЗначение = Число(ПрочитанноеЗначение);

    Исключение

    // Обработка ошибки преобразования

    КонецПопытки;

    КонецЕсли;

  2. Кодировка символов:

    При записи в файл укажите явную кодировку (например, КодировкаТекста.UTF8), иначе русские символы превратятся в ????.

  3. Циклические ссылки:

    Если структура A содержит ссылку на структуру B, а структура B — обратно на A, стандартная сериализация зациклится. Используйте внешние библиотеки с поддержкой ReferenceLoopHandling.

  4. Ограничения на размер:

    В веб-сервисах максимальный размер JSON-сообщения по умолчанию — 10 МБ. Для больших данных настройте параметр МаксимальныйРазмерПакета в конфигурации.

Для проверки корректности сериализации используйте валидаторы:

FAQ: Ответы на частые вопросы

Как сериализовать структуру с объектами 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);