Как исправить ошибку десериализации GUID при отправке JSON-запроса из 1С

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

При интеграции 1С с внешними веб-сервисами (особенно написанными на платформе .NET, такими как WCF или WebAPI) разработчики часто сталкиваются с неочевидной ошибкой при передаче уникальных идентификаторов. Текст ошибки обычно выглядит так: "Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Guid' because the type requires a JSON primitive value (e.g. string, number, boolean, null) to deserialize correctly".

В этой статье мы подробно разберем, почему возникает эта проблема, как JSON работает с типом GUID и каким образом правильно формировать тело запроса в 1С, чтобы сервер смог его обработать.

Суть проблемы: Примитив против Объекта

Давайте проанализируем ситуацию. Когда мы работаем с JSON, важно помнить, что в этом формате не существует отдельного типа данных "GUID" или "УникальныйИдентификатор". Для JSON любая информация — это либо строка, либо число, либо булево значение, либо NULL, либо сложный объект (массив или структура).

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

Рассмотрим пример типичного неправильного запроса, который формирует программист 1С:


// Неправильный подход
ТелоЗапроса = Новый Структура();
ТелоЗапроса.Вставить("CaseId", "d0080cae-f213-48a4-93f4-599c4647f5b4");

ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, ТелоЗапроса);
СтрокаJSON = ЗаписьJSON.Закрыть();
// Результат: {"CaseId":"d0080cae-f213-48a4-93f4-599c4647f5b4"}

В данном случае сервер видит объект с полем CaseId, в то время как программный метод на стороне сервиса ожидает, что всё тело запроса целиком является одним значением типа Guid.

Разбор стилей передачи параметров: Wrapped vs Bare

Чтобы понять, как правильно отправить запрос, проанализируем архитектуру веб-сервисов на базе .NET. Существует два основных стиля десериализации параметров из тела (Body) POST-запроса:

  1. Wrapped (Обернутый): Сервис ожидает объект JSON, ключи которого соответствуют именам аргументов функции. Это то, что мы привыкли видеть: {"ИмяПараметра": "Значение"}.
  2. Bare (Голый): Сервис ожидает, что содержимое тела запроса — это и есть значение параметра. Если параметр имеет тип Guid, то тело запроса должно содержать только строковый литерал в двойных кавычках.

Большинство ошибок "Cannot deserialize..." связано именно с тем, что метод API настроен на прием Bare-параметра, а 1С отправляет его в обертке из структуры.

Решение проблемы: Формирование «голого» GUID

Выясним, как изменить код 1С, чтобы отправить данные в нужном формате. Нам необходимо передать в тело запроса строку идентификатора, обрамленную в кавычки, без каких-либо дополнительных структур.

Посмотрим на пример правильной реализации:


// Правильный подход для передачи "голого" GUID
ИдентификаторДела = "d0080cae-f213-48a4-93f4-599c4647f5b4";

// Нам нужно получить строку: "d0080cae-f213-48a4-93f4-599c4647f5b4" (с кавычками!)
// Самый простой и надежный способ — использовать ЗаписьJSON для одного значения
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписьJSON.ЗаписатьЗначение(ИдентификаторДела);
ТелоЗапросаJSON = ЗаписьJSON.Закрыть();

// Теперь ТелоЗапросаJSON содержит строковое значение в кавычках, что является JSON-примитивом.

Обратите внимание, что использование ЗаписьJSON.ЗаписатьЗначение() гарантирует правильное экранирование и расстановку кавычек согласно стандарту. Если вы просто напишете ТелоЗапросаJSON = ИдентификаторДела, то отправите строку без кавычек, и сервер вернет ошибку, так как это не будет валидным JSON-примитивом.

Тонкости кодировки и Byte Order Mark (BOM)

Иногда даже при правильном формате тела запроса сервер может возвращать ошибку 400 Bad Request. Рассмотрим ситуацию, связанную с кодировкой текста и префиксом BOM. Проанализируем настройки метода УстановитьТелоИзСтроки.

Многие современные REST-сервисы чувствительны к наличию невидимых символов в начале потока данных. Если вы используете кодировку UTF-16 или принудительно включаете BOM, парсер на стороне сервера может "споткнуться" о первый же символ и не распознать начало JSON-строки.

Рекомендуется использовать стандартный для веба UTF-8 без BOM:


HTTPЗапрос = Новый HTTPЗапрос(АдресМетода, HTTPЗаголовок);
// Используем UTF-8 и явно отключаем использование BOM
HTTPЗапрос.УстановитьТелоИзСтроки(ТелоЗапросаJSON, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);

Проверка через инструменты отладки

Если решение выше не помогает, проанализируем ситуацию с помощью сниффера трафика, например, Fiddler или Charles. Это позволит увидеть, что именно уходит "в сыром виде" по сети.

При правильной настройке в инспекторе трафика (вкладка Raw или JSON) вы должны увидеть только идентификатор:

"ac556f2e-616d-4c07-9867-85febf0f6c06"

Если вы видите фигурные скобки { ... }, значит, вы все еще отправляете объект вместо примитива. Если вы видите странные символы в начале (например, ), значит, включен BOM, который нужно отключить.

Итоговые рекомендации

  1. Всегда уточняйте в документации к API, ожидает ли метод объект (Wrapped) или значение (Bare).
  2. Если сервер требует тип Guid, попробуйте отправить просто строку в кавычках.
  3. При работе с УникальныйИдентификатор в 1С всегда приводите его к строковому типу перед сериализацией с помощью функции Строка() или СокрЛП().
  4. Используйте ЗаписьJSON даже для одиночных значений, чтобы избежать ошибок форматирования.
  5. Для HTTP-заголовков всегда указывайте правильный Content-Type, например: HTTPЗаголовок.Вставить("Content-Type", "application/json; charset=utf-8");.

Соблюдение этих простых правил позволит избежать большинства проблем при интеграции 1С с внешними информационными системами через JSON-интерфейсы.

← На главную