При интеграции 1С с внешними системами через веб-сервисы (SOAP/REST) разработчики постоянно сталкиваются с необходимостью сопоставления данных. Типичная задача — определить, совпадают ли данные в полученном объекте ОбъектXDTO с существующим элементом справочника в базе данных (СправочникСсылка).
Напрямую сравнить эти два объекта через оператор «равно» (=) невозможно, поскольку они принадлежат к совершенно разным типам данных. В этой статье мы подробно разберем, как решить эту задачу, рассмотрим различные сценарии интеграции и научимся сопоставлять данные как вручную (пореквизитно), так и с помощью встроенных механизмов платформы 1С.
Если ваш пакет XDTO создан на основе метаданных 1С (например, при стандартном обмене между базами данных 1С), то самым простым решением будет автоматическая десериализация. Платформа 1С умеет самостоятельно преобразовывать XML/XDTO-объекты в прикладные типы данных.
Давайте разберем по шагам, как выполнить десериализацию для сравнения ссылок:
// Создаем сериализатор на основе используемой фабрики XDTO
Сериализатор = Новый СериализаторXDTO(ФабрикаXDTO);
Попытка
// Пробуем прочитать объект XDTO в стандартный тип 1С
СсылкаИзXDTO = Сериализатор.ПрочитатьXDTO(ОбъектXDTO);
// Если объект прочитан успешно, просто сравниваем ссылки
Если СсылкаИзXDTO = СсылкаСправочника Тогда
ОбъектыИдентичны = Истина;
Иначе
ОбъектыИдентичны = Ложь;
КонецЕсли;
Исключение
// Сюда мы попадем, если типы данных не соответствуют или структура XDTO некорректна
ОбъектыИдентичны = Ложь;
КонецПопытки;
Преимущества этого способа: минимум кода, высокая скорость работы и отсутствие необходимости вручную перебирать каждое свойство. Однако этот способ применим только в том случае, если схема XDTO строго соответствует типам метаданных вашей информационной базы.
Если объект XDTO получен из сторонней системы (например, внешнего сайта или ERP-системы стороннего разработчика), его структура гарантированно отличается от внутренней структуры 1С. В этом случае нам придется сравнивать значения реквизитов вручную в цикле.
Для реализации этого алгоритма нам необходимо решить две задачи: обойти реквизиты ссылки 1С и обойти свойства объекта XDTO. Давайте проанализируем, как это сделать.
Шаг 1. Перебор реквизитов справочника 1С через метаданные
Для обхода всех реквизитов справочника воспользуемся коллекцией метаданных объекта:
Для Каждого Реквизит Из СсылкаСправочника.Метаданные().Реквизиты Цикл
ИмяРеквизита = Реквизит.Имя;
ЗначениеРеквизита = СсылкаСправочника[ИмяРеквизита];
// Здесь будет происходить сравнение со свойством XDTO
КонецЦикла;
Шаг 2. Обход свойств объекта XDTO
На форумах часто совершают ошибку, пытаясь перебрать объект XDTO обычным циклом Для Каждого. Это вызывает ошибку выполнения. Для правильного обхода необходимо использовать метод Свойства():
Для Каждого Свойство Из ОбъектXDTO.Свойства() Цикл
ИмяСвойства = Свойство.Имя;
ЗначениеXDTO = ОбъектXDTO.Получить(Свойство); // либо ОбъектXDTO[ИмяСвойства]
// Выполняем сравнение со значением из 1С
КонецЦикла;
Шаг 3. Объединение в единый алгоритм сравнения
Давайте напишем универсальную функцию, которая будет сравнивать только те свойства XDTO, имена которых совпадают с реквизитами справочника 1С:
Функция ДанныеСовпадают(СсылкаСправочника, ОбъектXDTO) Экспорт
МетаданныеСправочника = СсылкаСправочника.Метаданные();
// Проверяем основные свойства (Код и Наименование), если они есть в XDTO
Если ОбъектXDTO.Свойства().Получить("Code") <> Неопределено Тогда
Если СокрЛП(СсылкаСправочника.Код) <> СокрЛП(ОбъектXDTO.Code) Тогда
Возврат Ложь;
КонецЕсли;
КонецЕсли;
Если ОбъектXDTO.Свойства().Получить("Description") <> Неопределено Тогда
Если СокрЛП(СсылкаСправочника.Наименование) <> СокрЛП(ОбъектXDTO.Description) Тогда
Возврат Ложь;
КонецЕсли;
КонецЕсли;
// Перебираем дополнительные реквизиты справочника 1С
Для Каждого Реквизит Из МетаданныеСправочника.Реквизиты Цикл
ИмяРеквизита = Реквизит.Имя;
// Ищем свойство в XDTO с таким же именем
СвойствоXDTO = ОбъектXDTO.Свойства().Получить(ИмяРеквизита);
Если СвойствоXDTO <> Неопределено Тогда
Значение1С = СсылкаСправочника[ИмяРеквизита];
ЗначениеXDTO = ОбъектXDTO.Получить(СвойствоXDTO);
// Выполняем сравнение с учетом типов данных
Если Не ЗначенияРавны(Значение1С, ЗначениеXDTO) Тогда
Возврат Ложь;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Возврат Истина;
КонецФункции
При написании логики сравнения вы обязательно столкнетесь со спецификой типов данных. Давайте разберем наиболее частые проблемы и способы их решения:
Ложь.
Решение: Преобразуйте ссылку 1С в строку GUID перед сравнением:
Строка(СсылкаНаОбъект.УникальныйИдентификатор())
ИНН может соответствовать свойство inn или taxpayer_id.
Решение: Создайте вспомогательное Соответствие (маппинг), где ключом будет имя свойства XDTO, а значением — имя реквизита в 1С.
client-id), то 1С при импорте автоматически заменит дефисы на нижние подчеркивания (client_id). Это необходимо учитывать при динамическом поиске свойств.
Используя предложенные методики, вы сможете быстро и без ошибок реализовать сравнение данных любой сложности при интеграции ваших решений на платформе 1С:Предприятие.