При организации обмена данными между двумя базами 1С (даже с идентичными конфигурациями) разработчики часто выбирают механизм XDTO как наиболее стандартизированный и удобный. Однако при использовании связки СериализаторXDTO и формата JSON можно столкнуться с неприятной ситуацией: существующие в обеих базах элементы синхронизируются успешно, а новые объекты в базе-приемнике не создаются, вместо этого отображается сообщение ОбъектНеНайден. В рамках этой статьи мы подробно разберем, почему это происходит и как правильно организовать передачу данных, чтобы новые элементы корректно создавались в целевой базе.
Давайте проанализируем ситуацию, с которой столкнулся автор темы. Проблема кроется в фундаментальном различии между типами СправочникСсылка и СправочникОбъект (или их аналогами для документов и других метаданных) при их сериализации.
Когда мы передаем данные через СериализаторXDTO, система ведет себя по-разному в зависимости от того, что именно подается на вход:
СправочникСсылка, в формируемый JSON записывается только уникальный идентификатор (GUID) и тип объекта. При чтении этого JSON в другой базе метод ПрочитатьJSON видит GUID. Он пытается найти в текущей базе объект с таким идентификатором. Если объект не найден (так как это новый элемент, созданный в другой базе), система возвращает «битую» ссылку со строковым представлением Объект не найден. Новая запись в базе при этом не создается.СправочникОбъект. В этом случае сериализатор включает в пакет данных не только идентификатор, но и все реквизиты объекта, его табличные части и свойства.Рассмотрим по шагам процесс правильной подготовки данных в базе-источнике. Вместо того чтобы просто добавлять ссылку в массив для отправки, нам нужно получить сам объект. Проанализируем пример кода для отправки данных через веб-сервис:
// В базе-источнике
Запрос = Новый Запрос("ВЫБРАТЬ Ссылка ИЗ Справочник.Номенклатура ГДЕ ЭтоНовыйОбъект = ИСТИНА");
Выборка = Запрос.Выполнить().Выбрать();
МассивОбъектов = Новый Массив;
Пока Выборка.Следующий() Цикл
// КРИТИЧЕСКИ ВАЖНО: Получаем объект, а не ссылку
ДанныеОбъекта = Выборка.Ссылка.ПолучитьОбъект();
МассивОбъектов.Добавить(ДанныеОбъекта);
КонецЦикла;
// Далее сериализуем массив объектов в JSON
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
СериализаторXDTO.ЗаписатьJSON(ЗаписьJSON, МассивОбъектов);
СтрокаJSON = ЗаписьJSON.Закрыть();
Именно метод ПолучитьОбъект() позволяет СериализаторуXDTO понять, что нужно выгрузить не просто "указатель" на запись, а все её содержимое.
Выясним, что происходит на стороне базы-приемника. Когда мы вызываем СериализаторXDTO.ПрочитатьJSON(ЧтениеJSON), система создает в оперативной памяти экземпляр объекта 1С. Однако важно помнить: десериализация не записывает объект в базу данных автоматически.
Посмотрим на алгоритм обработки полученных данных:
// В базе-приемнике
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(ПолученнаяСтрокаJSON);
// Получаем массив объектов (десериализация)
ДанныеИзJSON = СериализаторXDTO.ПрочитатьJSON(ЧтениеJSON);
Для Каждого ТекущийОбъект Из ДанныеИзJSON Цикл
// Проверяем, что это именно объект, готовый к записи
Если ТипЗнч(ТекущийОбъект) = Тип("СправочникОбъект.Номенклатура") Тогда
Попытка
// Устанавливаем признак обмена, чтобы не зациклить миграцию
ТекущийОбъект.ОбменДанными.Загрузка = Истина;
ТекущийОбъект.Записать();
Исключение
Сообщить("Ошибка при записи объекта: " + ОписаниеОшибки());
КонецПопытки;
КонецЕсли;
КонецЦикла;
Обратите внимание на свойство ОбменДанными.Загрузка = Истина. Это критически важный момент при программной записи объектов, полученных извне. Он позволяет игнорировать стандартные проверки при записи (если это допустимо логикой вашего обмена), чтобы обеспечить идентичность данных в обеих базах.
Рассмотрим подробнее, почему иногда даже при передаче объекта могут возникать ошибки. СериализаторXDTO жестко завязан на метаданные конфигурации. Если конфигурации в базах источника и приемника различаются (например, в приемнике нет какого-то реквизита, который есть в источнике), метод ПрочитатьJSON может вызвать исключение или пропустить часть данных.
В JSON-структуре, создаваемой 1С, всегда присутствует служебное поле "#type". Оно указывает на URI пространства имен и имя типа. Если базы имеют разные версии, URI могут не совпадать. В таких случаях рекомендуется использовать работу через промежуточные ОбъектыXDTO.
Разберем, как это работает через ПрочитатьXDTO:
ОбъектXDTO.СериализаторXDTO.ПрочитатьXDTO(МойОбъектXDTO) для получения итогового объекта 1С.Проанализируем ситуацию, когда вы передаете объект «Номенклатура», у которого есть реквизит «ВидНоменклатуры» (ссылка). Если в базе-приемнике нет элемента «ВидНоменклатуры» с таким же GUID, как в источнике, то после загрузки в поле «ВидНоменклатуры» нового товара вы снова увидите Объект не найден.
Как с этим бороться? Рассмотрим два основных подхода:
Выясним, всегда ли стоит использовать СериализаторXDTO. При передаче очень больших массивов данных (десятки тысяч строк) этот метод может работать медленнее, чем ручное формирование JSON. Это связано с тем, что СериализаторXDTO добавляет много служебной информации о типах данных в каждое поле.
Если ваша задача — максимально быстрая передача данных и вы контролируете структуру обеих баз, иногда эффективнее использовать обычную Структуру, заполнять её данными объекта и сериализовать методом ЗаписатьJSON без использования XDTO. В этом случае на стороне приемника вам придется вручную создавать объект и заполнять его реквизиты, но скорость обработки данных может возрасти в разы.
Подводя итог, кратко сформулируем основные правила успешного обмена через СериализаторXDTO:
Объект (через ПолучитьОбъект()), а не Ссылку.Записать() после десериализации, иначе данные останутся только в оперативной памяти.ОбменДанными.Загрузка = Истина для корректного переноса идентификаторов (GUID).Соблюдение этих простых правил позволит вам избежать ошибки ОбъектНеНайден и сделает ваши механизмы интеграции надежными и предсказуемыми.