При интеграции 1С с внешними сервисами, использующими REST API и формат JSON, мы часто сталкиваемся с необходимостью десериализации данных. Для этого в 1С удобно использовать объект ФабрикаXDTO. Однако иногда возникает загадочная ситуация, когда один и тот же код, успешно работающий на клиенте, внезапно начинает выдавать ошибку на сервере. Давайте вместе разберем эту проблему и найдем ее решение.
Представим типовой сценарий: выгрузка товаров в ОЗОН через Яндекс Диск, где используется API. Все работало исправно в течение нескольких месяцев, но в один прекрасный день серверная часть перестала обрабатывать ответы от Яндекс Диска, выдавая ошибку. Клиентская же часть при этом продолжает работать без проблем, используя те же самые данные и методы.
Посмотрим на пример кода, который демонстрирует это поведение:
&НаСервере
Процедура ЖСОНСервер()
// ТУТ НЕ РАБОТАЕТ
ЧтениеJSON = Новый ЧтениеJSON();
ЧтениеJSON.УстановитьСтроку(Объект.ТекстОбъекта);
ТипОбъекта = ФабрикаXDTO.Тип("cloud-api.yandex.net/v1/disk", "uploadGetResponse");
__Объект = ФабрикаXDTO.ПрочитатьJSON(ЧтениеJSON, ТипОбъекта);
КонецПроцедуры
&НаКлиенте
Процедура жосн(Команда)
//////////////// ТУТ РАБОТАЕТ ///////////////////
ЧтениеJSON = Новый ЧтениеJSON();
ЧтениеJSON.УстановитьСтроку(Объект.ТекстОбъекта);
ТипОбъекта = ФабрикаXDTO.Тип("cloud-api.yandex.net/v1/disk", "uploadGetResponse");
__Объект = ФабрикаXDTO.ПрочитатьJSON(ЧтениеJSON, ТипОбъекта);
ЖСОНСервер();
КонецПроцедуры
В данном примере Объект.ТекстОбъекта содержит JSON-строку, полученную от Яндекс Диска, например, такую:
{"method":"PUT","href":"https://uploader99klg.disk.yandex.net:443/upload-target/20250530T105738.233.utd.16xmn5oe82whiuqfx3aalxwei-k99klg.4087635","templated":false ,"operation_id":"e6edb64271e173f178264c2fdf0d9eb7f08e92fbec09156d4e2a811b33607e7a"}
При вызове метода ФабрикаXDTO.ПрочитатьJSON() на сервере мы получаем следующую ошибку:
Ошибка при вызове метода контекста (ПрочитатьJSON)
{ВнешняяОбработка.ВнешняяОбработка1.Форма.Форма.Форма(18)}:__Объект = ФабрикаXDTO.ПрочитатьJSON(ЧтениеJSON, ТипОбъекта);
{ВнешняяОбработка.ВнешняяОбработка1.Форма.Форма.Форма(33)}:ЖСОНСервер();
[ОшибкаВоВремяВыполненияВстроенногоЯзыка]
по причине:Ошибка преобразования данных XDTO:
Чтение объекта типа: {cloud-api.yandex.net/v1/disk}uploadGetResponse
Проверка свойства 'method':
форма: Элемент
имя: {cloud-api.yandex.net/v1/disk}method
тип: {http://www.w3.org/2001/XMLSchema}string
по причине:Ошибка проверки данных XDTO:
Структура объекта не соответствует типу: {cloud-api.yandex.net/v1/disk}uploadGetResponse
Проверка свойства 'method':
форма: Элемент
имя: {cloud-api.yandex.net/v1/disk}method
тип: {http://www.w3.org/2001/XMLSchema}string
Не установлено значение одного из следующих свойств: operation_id
Ошибка явно указывает на проблему с валидацией данных XDTO и упоминает, что "Не установлено значение одного из следующих свойств: operation_id", хотя в приходящей JSON-строке это свойство присутствует.
Чтобы выяснить причину такого поведения, нам необходимо проанализировать несколько ключевых моментов:
uploadGetResponse. Давайте посмотрим на определение этого типа в XDTO-пакете, который был импортирован из XSD-схемы Яндекс Диска:
Обратите внимание на тег <xs:sequence>. Этот тег в XSD-схемах означает, что порядок следования элементов должен быть строго соблюден. То есть, 1С, основываясь на этой схеме, ожидает, что поля в JSON-ответе будут идти именно в таком порядке: сначала operation_id, затем href, method и templated.
operation_id, href, method, templated.method, href, templated, operation_id.method идет первым, тогда как схема ожидает operation_id.Почему же возникает ошибка "Не установлено значение одного из следующих свойств: operation_id"? Серверный парсер ФабрикаXDTO, работая в строгом режиме и видя <xs:sequence> в схеме, ожидает найти operation_id на первой позиции. Когда он обнаруживает там method, он расценивает это как несоответствие и считает, что operation_id "не установлено" в ожидаемой позиции, даже если оно присутствует дальше в JSON-строке.
Как оказалось, внешние API, такие как Яндекс Диск, могут менять порядок полей в JSON-ответах, поскольку стандарт JSON (RFC 7159) определяет объекты как неупорядоченные коллекции пар "имя/значение". Это означает, что порядок полей в JSON-объекте не гарантируется и может изменяться.
Ключевым моментом для решения этой проблемы является изменение одного свойства в определении типа uploadGetResponse в вашем XDTO-пакете. Нам необходимо установить свойство "Упорядоченный" (Ordered) в значение Ложь.
Давайте разберем по шагам, как это сделать:
Общие, затем выберите XDTO-пакеты.cloud-api.yandex.net/v1/disk).uploadGetResponse.uploadGetResponse и в окне свойств этого типа (обычно внизу или справа) найдите свойство Упорядоченный.Ложь.После сохранения изменений и обновления конфигурации базы данных, ваш серверный код с ФабрикаXDTO.ПрочитатьJSON() должен начать работать корректно.
Давайте рассмотрим подробнее, как работает свойство Упорядоченный и почему его изменение решает нашу проблему:
Упорядоченный = Истина (значение по умолчанию):
Когда это свойство установлено в Истина (что часто является значением по умолчанию для типов, импортированных из XSD-схем, использующих <xs:sequence>), механизм ФабрикаXDTO ожидает, что поля во входящем JSON-документе будут расположены в точно таком же порядке, как они описаны в XDTO-схеме. Если порядок нарушен, возникает ошибка валидации, особенно строго на серверной стороне.
Упорядоченный = Ложь:
Если свойство Упорядоченный установлено в Ложь, то при чтении входящих данных порядок следования элементов не контролируется. Это означает, что парсер XDTO будет искать поля по их именам, игнорируя их позицию в JSON-строке. Именно это объясняет, почему установка этого свойства в Ложь решила нашу проблему на сервере: ФабрикаXDTO перестала требовать строгий порядок полей и смогла корректно сопоставить данные из JSON с определениями в XDTO-схеме, независимо от их расположения.
Важно помнить, что стандарт JSON определяет объекты как неупорядоченные коллекции. Внешние API могут возвращать поля в JSON-объектах в произвольном порядке, и этот порядок может меняться со временем без предупреждения. Если ваша XDTO-схема в 1С ожидает строгий порядок, это может привести к внезапным ошибкам при десериализации.
Проанализировав эту ситуацию, мы можем сформулировать несколько рекомендаций для более надежной работы с внешними REST API в 1С:
Упорядоченный = Ложь для JSON-объектов. Для типов объектов XDTO, которые соответствуют JSON-объектам и могут иметь переменный порядок полей, рекомендуется устанавливать свойство Упорядоченный в Ложь в XDTO-пакете. Это значительно повысит устойчивость вашей интеграции к изменениям порядка полей во внешних системах.ФабрикаXDTO. Механизм XDTO в 1С, изначально разработанный для XML, был адаптирован для работы с JSON, но имеет свои нюансы в валидации и интерпретации схем. Понимание этих особенностей поможет вам избежать подобных проблем в будущем.Таким образом, мы выяснили, что причиной проблемы является строгая валидация порядка полей в XDTO-схеме на серверной стороне 1С, которая по умолчанию ожидает порядок, определенный тегом <xs:sequence>. Изменив свойство Упорядоченный на Ложь для соответствующего типа XDTO, мы разрешаем парсеру игнорировать порядок полей, что делает интеграцию более гибкой и устойчивой к изменениям во внешних API.