Как правильно сериализовать и прочитать простые данные через XML в 1С?

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

При разработке интеграционных механизмов, обмене сообщениями или сохранении настроек разработчики часто сталкиваются с необходимостью быстро перевести объект платформы (например, строку, число или структуру) в XML-строку и восстановить его обратно. Однако простая попытка вызвать методы ЗаписатьXML и ПрочитатьXML нередко приводит к ошибкам вида «Ошибка преобразования данных XML» или сбоям модели XDTO. Разберем по шагам, почему возникают эти исключения и как правильно реализовать сериализацию и десериализацию данных.

Анализ первой проблемы: «Ошибка преобразования данных XML» при вызове ПрочитатьXML

Рассмотрим типовой сценарий, с которого часто начинаются эксперименты с сериализацией:


Функция ВXML(Строка) Экспорт
    ЗаписьXML = Новый ЗаписьXML;
    ЗаписьXML.УстановитьСтроку();
    ЗаписатьXML(ЗаписьXML, Строка);
    Возврат ЗаписьXML.Закрыть();
КонецФункции

Функция ИзXML(Стр) Экспорт
    ЧтениеXML = Новый ЧтениеXML;
    ЧтениеXML.УстановитьСтроку(Стр);
    Возврат ПрочитатьXML(ЧтениеXML);
КонецФункции

Вызов метода ПрочитатьXML(ЧтениеXML) в данном примере завершается аварийно. Выясним причину такого поведения. Дело в том, что процедура ЗаписатьXML(ЗаписьXML, Значение) принимает необязательный третий параметр — НазначениеТипаXML, значением по умолчанию для которого является НазначениеТипаXML.Неявное. При неявном назначении типа примитивные значения (строки, числа, булевы флаги) записываются в поток без атрибута схемы xsi:type. В результате в сформированной строке отсутствует информация о том, какой именно тип платформы был упакован в XML-узел. Когда функция ПрочитатьXML пытается восстановить значение, не имея подсказки в виде атрибута типа и без явного указания второго параметра, она не может сопоставить узел ни с одним типом данных и выбрасывает исключение.

Для устранения этой ошибки у нас есть два пути:

  1. Явно указывать тип при считывании: передать методу второй параметр — ожидаемый тип значения. Например: ПрочитатьXML(ЧтениеXML, Тип("Строка")). Этот вариант удобен, когда структура пакета строго фиксирована и тип данных заранее известен принимающей стороне.
  2. Использовать явное указание типа при сериализации: передавать в процедуру записи признак НазначениеТипаXML.Явное. В этом случае узел получит атрибут с указанием типа (например, xsi:type="xs:string"), и метод ПрочитатьXML сможет определить его автоматически без дополнительных параметров.

Использование СериализаторXDTO для универсальной сериализации

В типовых конфигурациях (в том числе в Библиотеке стандартных подсистем) для упаковки произвольных сериализуемых значений в XML применяется объект СериализаторXDTO. Посмотрим на надежный и универсальный пример функций:


Функция ЗначениеВСтрокуXML(Значение) Экспорт
    ЗаписьXML = Новый ЗаписьXML;
    ЗаписьXML.УстановитьСтроку();
    
    // Явно указываем сериализатору необходимость добавлять атрибут типа
    СериализаторXDTO.ЗаписатьXML(ЗаписьXML, Значение, НазначениеТипаXML.Явное);
    
    Возврат ЗаписьXML.Закрыть();
КонецФункции

Функция ЗначениеИзСтрокиXML(СтрокаXML) Экспорт
    ЧтениеXML = Новый ЧтениеXML;
    ЧтениеXML.УстановитьСтроку(СтрокаXML);
    
    // Проверяем возможность десериализации и считываем объект
    Возврат СериализаторXDTO.ПрочитатьXML(ЧтениеXML);
КонецФункции

Параметр НазначениеТипаXML.Явное гарантирует, что внутри XML-разметки будет присутствовать описание типа XSD. Благодаря этому десериализатор безошибочно распознает тип и создаст соответствующий объект 1С при чтении.

Для повышения надежности чтения перед вызовом СериализаторXDTO.ПрочитатьXML рекомендуется выполнять проверку:


Если СериализаторXDTO.ВозможностьЧтенияXML(ЧтениеXML) Тогда
    Возврат СериализаторXDTO.ПрочитатьXML(ЧтениеXML);
КонецЕсли;

Обратите внимание: если XML-документ содержит служебный пролог (декларацию вида <?xml version="1.0" encoding="UTF-8"?>) или пробельные символы перед корневым элементом, чтению может потребоваться предварительное позиционирование на открывающий тег с помощью вызова ЧтениеXML.Прочитать().

Анализ второй проблемы: «Ошибка при вызове метода объекта модели XDTO. Неверный параметр»

Иногда при выполнении полностью корректного кода на мобильной платформе или в конфигурации с назначением «Мобильное приложение» возникает ошибка XDTO-модели. Проанализируем ситуацию.

В платформе «1С:Предприятие» контекст СериализаторXDTO тесно связан с внутренней фабрикой метаданных конфигурации (пакетом current-config). На мобильной платформе состав поддерживаемых типов данных ограничен по сравнению с десктопной версией. Если конфигурация разрабатывалась для настольного приложения, а затем в ее свойствах было изменено «Назначение использования» на «Мобильное приложение», может произойти рассинхронизация внутренней фабрики типов и кэша метаданных.

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

Как исправить данное поведение:

  1. Пересборка конфигурации: полностью выгрузите конфигурацию в файл (.cf), загрузите ее заново в чистую информационную базу и повторно выставьте свойство «Мобильное приложение». Это принудительно перестроит внутренние фабрики XDTO под мобильный состав метаданных.
  2. Очистка кэша разработки: удалите временные файлы сеанса и кэш метаданных информационной базы. Поврежденный кэш XDTO-схем — частая причина ложных ошибок десериализации.
  3. Контроль типов данных: убедитесь, что в сериализуемых данных не передаются объекты метаданных или сложные типы, не поддерживаемые мобильной платформой.

Альтернативные и легковесные способы сериализации примитивных типов

Если ваша задача сводится исключительно к передаче базовых типов (строка, число, дата, булево, уникальный идентификатор), использовать связку ЗаписьXML / ЧтениеXML и фабрику XDTO не обязательно. Платформа предоставляет компактные функции:

  1. Методы XMLСтрока и XMLЗначение:

    Функция XMLСтрока(Значение) формирует текстовое строковое представление значения в формате XML без обертывания в XML-теги. Для обратного преобразования используется функция XMLЗначение(Тип, СтрокаXML):

    
    // Преобразование в строковое представление XML
    ТекстXML = XMLСтрока(ТекущаяДата());
    
    // Восстановление значения требуемого типа
    ИсходнаяДата = XMLЗначение(Тип("Дата"), ТекстXML);
    

    Эти функции работают предельно быстро, не создают накладных расходов на создание объектов потокового чтения/записи и полностью изолированы от структуры метаданных конфигурации.

  2. Сериализация в JSON:

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

← На главную