Как исправить ошибку преобразования данных XDTO при использовании веб-сервисов в 1С?

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

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

Разбор причины возникновения ошибки

Рассмотрим стандартную ситуацию: через веб-сервис мы получаем объект типа ОбъектXDTO. Для удобства или логирования мы преобразуем его в строку с помощью функции ОбщегоНазначения.ОбъектXDTOВСтрокуXML. Однако, когда мы пытаемся выполнить обратное преобразование функцией ОбщегоНазначения.ЗначениеИзСтрокиXML, система выдает исключение.

Выясним причину. Функция ЗначениеИзСтрокиXML внутри себя использует объект СериализаторXDTO. Этот механизм предназначен исключительно для встроенных типов платформы 1С, таких как Структура, Массив, ТаблицаЗначений или ссылки на объекты метаданных (СправочникСсылка и др.).

Когда СериализаторXDTO встречает в XML данные, структура которых описана во внешней схеме XSD или передана сторонним сервисом (не по стандартам внутренней сериализации 1С), он не может сопоставить это «НачалоСвойства» ни с одним внутренним типом и выдает ошибку. Для работы с произвольными данными XDTO нужно использовать Фабрику XDTO.

Решение 1: Использование специализированных функций БСП

Если в вашей конфигурации используется Библиотека стандартных подсистем (БСП), для работы с XDTO-объектами предусмотрены отдельные инструменты. Вместо универсальной функции ЗначениеИзСтрокиXML, проанализируем и применим функцию ОбъектXDTOИзСтрокиXML.

Этот метод специально адаптирован для десериализации данных, которые не являются системными типами 1С. Рассмотрим пример вызова:


// Получаем строку XML из внешнего источника или переменной
СтрокаXML = ПолучитьДанныеВФорматеXML(); 

// ТипXDTO - это объект типа ТипОбъектаXDTO, который мы ожидаем получить
// Его можно получить из пакета XDTO или фабрики
МойОбъект = ОбщегоНазначения.ОбъектXDTOИзСтрокиXML(СтрокаXML, ТипXDTO);

Решение 2: Прямое чтение через Фабрику XDTO

Если нам нужно более гибкое управление процессом или БСП недоступна, мы воспользуемся методом ПрочитатьXML самой фабрики. Это наиболее надежный способ, так как он позволяет явно указать схему, по которой будет производиться разбор.

Разберем процесс по шагам:

  1. Создадим объект ЧтениеXML и загрузим в него нашу строку.
  2. Обратимся к глобальной ФабрикеXDTO (или созданной на основе вашей XSD-схемы).
  3. Вызовем метод чтения, указав ожидаемый тип.

Чтение = Новый ЧтениеXML;
Чтение.УстановитьСтроку(СтрокаXML);

// Если тип заранее известен (из пакета XDTO в конфигурации)
ТипОбъекта = ФабрикаXDTO.Тип("http://www.your-namespace.com", "Order");
РезультатXDTO = ФабрикаXDTO.ПрочитатьXML(Чтение, ТипОбъекта);

// Если тип неизвестен (AnyType), можно пробовать читать без второго параметра
// РезультатXDTO = ФабрикаXDTO.ПрочитатьXML(Чтение);

Важный нюанс: Проанализируем пространство имен (Namespace). Если в XML-строке не указано URI пространства имен или оно пустое, это может привести к ошибке даже при использовании фабрики. Убедитесь, что передаваемый XML соответствует схеме, описанной в 1С.

Решение 3: Преобразование XDTO в привычные типы (Структура, ТЗ)

Зачастую работать напрямую с объектом XDTO неудобно, особенно если нужно заполнять документ «Заказ покупателя». Мы можем преобразовать XDTO-объект в обычную структуру 1С. В БСП для этого есть удобный метод:


// Преобразует свойства XDTO в ключи структуры
ДанныеСтруктура = ОбменДаннымиXDTOСервер.ОбъектXDTOВСтруктуру(ОбъектXDTO);

Если же данные представляют собой список (массив объектов), нам потребуется обход в цикле для заполнения ТаблицыЗначений. Рассмотрим пример реализации:


ТЗ_Товары = Новый ТаблицаЗначений;
// Допустим, ОбъектXDTO содержит коллекцию "Items"
Если ОбъектXDTO.Items.Количество() > 0 Тогда
    // Создаем колонки по свойствам первого элемента
    Для Каждого Свойство Из ОбъектXDTO.Items[0].Тип().Свойства Цикл
        ТЗ_Товары.Колонки.Добавить(Свойство.Имя);
    КонецЦикла;
    
    // Наполняем таблицу данными
    Для Каждого ТекущийЭлемент Из ОбъектXDTO.Items Цикл
        НоваяСтрока = ТЗ_Товары.Добавить();
        ЗаполнитьЗначенияСвойств(НоваяСтрока, ТекущийЭлемент);
    КонецЦикла;
КонецЕсли;

Как отладить внешний вызов веб-сервиса?

Основная сложность при работе с веб-сервисами заключается в том, что обычная точка останова в коде модуля веб-сервиса может не сработать, так как обращение идет из внешнего сеанса. Посмотрим, как мы можем это обойти:

  1. Логирование в файл: Это самый простой и эффективный метод. Запишите полученную XML-строку в текстовый файл на диске сервера. После этого создайте обычную внешнюю обработку, которая считывает этот файл, и запускайте ее под отладчиком в обычном клиенте. Так вы сможете детально проанализировать структуру объекта.
  2. Настройка сервера: Убедитесь, что в файле публикации default.vrd в параметре debug установлено значение true. Также проверьте наличие файла конфигурации webservicecfg.xml в папке bin/conf сервера 1С.
  3. Эмуляция ответа: Используйте инструменты типа Postman или SoapUI, чтобы увидеть «сырой» ответ от сервиса. Иногда ошибка кроется в невидимых спецсимволах или неправильной кодировке.

Подводя итог, отметим: если вы видите ошибку «НачалоСвойства», значит, вы пытаетесь использовать СериализаторXDTO там, где должна работать ФабрикаXDTO. Используйте правильные методы десериализации, проверяйте пространства имен и всегда имейте под рукой сохраненный XML-дамп для локальной отладки.

← На главную