Почему СериализаторXDTO возвращает «Объект не найден» при чтении JSON и как это исправить?

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

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

Разбор основной причины: Ссылка против Объекта

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

Когда мы передаем данные через СериализаторXDTO, система ведет себя по-разному в зависимости от того, что именно подается на вход:

Как правильно подготовить данные для отправки

Рассмотрим по шагам процесс правильной подготовки данных в базе-источнике. Вместо того чтобы просто добавлять ссылку в массив для отправки, нам нужно получить сам объект. Проанализируем пример кода для отправки данных через веб-сервис:


// В базе-источнике
Запрос = Новый Запрос("ВЫБРАТЬ Ссылка ИЗ Справочник.Номенклатура ГДЕ ЭтоНовыйОбъект = ИСТИНА");
Выборка = Запрос.Выполнить().Выбрать();

МассивОбъектов = Новый Массив;
Пока Выборка.Следующий() Цикл
    // КРИТИЧЕСКИ ВАЖНО: Получаем объект, а не ссылку
    ДанныеОбъекта = Выборка.Ссылка.ПолучитьОбъект();
    МассивОбъектов.Добавить(ДанныеОбъекта);
КонецЦикла;

// Далее сериализуем массив объектов в 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:

  1. Сначала мы считываем данные не напрямую в объект 1С, а в универсальный объект ОбъектXDTO.
  2. Это дает нам возможность программно проанализировать структуру данных, поменять GUID или подменить тип, если это необходимо.
  3. Затем мы используем СериализаторXDTO.ПрочитатьXDTO(МойОбъектXDTO) для получения итогового объекта 1С.

Особенности ссылочных реквизитов внутри объекта

Проанализируем ситуацию, когда вы передаете объект «Номенклатура», у которого есть реквизит «ВидНоменклатуры» (ссылка). Если в базе-приемнике нет элемента «ВидНоменклатуры» с таким же GUID, как в источнике, то после загрузки в поле «ВидНоменклатуры» нового товара вы снова увидите Объект не найден.

Как с этим бороться? Рассмотрим два основных подхода:

Рекомендации по производительности

Выясним, всегда ли стоит использовать СериализаторXDTO. При передаче очень больших массивов данных (десятки тысяч строк) этот метод может работать медленнее, чем ручное формирование JSON. Это связано с тем, что СериализаторXDTO добавляет много служебной информации о типах данных в каждое поле.

Если ваша задача — максимально быстрая передача данных и вы контролируете структуру обеих баз, иногда эффективнее использовать обычную Структуру, заполнять её данными объекта и сериализовать методом ЗаписатьJSON без использования XDTO. В этом случае на стороне приемника вам придется вручную создавать объект и заполнять его реквизиты, но скорость обработки данных может возрасти в разы.

Итоги

Подводя итог, кратко сформулируем основные правила успешного обмена через СериализаторXDTO:

  1. Если нужно создать новый элемент в приемнике — всегда передавайте Объект (через ПолучитьОбъект()), а не Ссылку.
  2. Всегда вызывайте метод Записать() после десериализации, иначе данные останутся только в оперативной памяти.
  3. Следите за идентичностью метаданных в обеих базах.
  4. Используйте ОбменДанными.Загрузка = Истина для корректного переноса идентификаторов (GUID).

Соблюдение этих простых правил позволит вам избежать ошибки ОбъектНеНайден и сделает ваши механизмы интеграции надежными и предсказуемыми.

← На главную