При интеграции 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.
Чтобы понять, как правильно отправить запрос, проанализируем архитектуру веб-сервисов на базе .NET. Существует два основных стиля десериализации параметров из тела (Body) POST-запроса:
{"ИмяПараметра": "Значение"}.Guid, то тело запроса должно содержать только строковый литерал в двойных кавычках.Большинство ошибок "Cannot deserialize..." связано именно с тем, что метод API настроен на прием Bare-параметра, а 1С отправляет его в обертке из структуры.
Выясним, как изменить код 1С, чтобы отправить данные в нужном формате. Нам необходимо передать в тело запроса строку идентификатора, обрамленную в кавычки, без каких-либо дополнительных структур.
Посмотрим на пример правильной реализации:
// Правильный подход для передачи "голого" GUID
ИдентификаторДела = "d0080cae-f213-48a4-93f4-599c4647f5b4";
// Нам нужно получить строку: "d0080cae-f213-48a4-93f4-599c4647f5b4" (с кавычками!)
// Самый простой и надежный способ — использовать ЗаписьJSON для одного значения
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписьJSON.ЗаписатьЗначение(ИдентификаторДела);
ТелоЗапросаJSON = ЗаписьJSON.Закрыть();
// Теперь ТелоЗапросаJSON содержит строковое значение в кавычках, что является JSON-примитивом.
Обратите внимание, что использование ЗаписьJSON.ЗаписатьЗначение() гарантирует правильное экранирование и расстановку кавычек согласно стандарту. Если вы просто напишете ТелоЗапросаJSON = ИдентификаторДела, то отправите строку без кавычек, и сервер вернет ошибку, так как это не будет валидным JSON-примитивом.
Иногда даже при правильном формате тела запроса сервер может возвращать ошибку 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, который нужно отключить.
Guid, попробуйте отправить просто строку в кавычках.УникальныйИдентификатор в 1С всегда приводите его к строковому типу перед сериализацией с помощью функции Строка() или СокрЛП().ЗаписьJSON даже для одиночных значений, чтобы избежать ошибок форматирования.Content-Type, например: HTTPЗаголовок.Вставить("Content-Type", "application/json; charset=utf-8");.Соблюдение этих простых правил позволит избежать большинства проблем при интеграции 1С с внешними информационными системами через JSON-интерфейсы.