При интеграции 1С с внешними системами через API часто возникает специфическая задача: необходимо передать значение null именно как литерал JSON (без кавычек), а не как пустую строку или слово "null" в кавычках. В 1С существует путаница между типами NULL, Неопределено и ПустаяСсылка, что часто приводит к ошибкам при сериализации. Разберем подробно, как реализовать корректную запись в разных сценариях: от простых структур до сложных XDTO-пакетов, особенно когда вы проходите интерактивный курс по работе с HTTP-запросами и JSON.
Прежде всего, проанализируем, почему возникает проблема. В языке 1С тип NULL используется исключительно для работы с базой данных (например, когда в результате левого соединения отсутствует запись). Тип Неопределено является универсальным маркером отсутствия значения в объектах и переменных. Для JSON-сериализатора 1С аналогом литерала null является именно Неопределено.
Если вы попытаетесь передать значение NULL (из результата запроса) напрямую в метод ЗаписатьJSON, система может либо выдать ошибку, либо попытаться привести его к строке, что даст неверный результат. При работе с 1C и универсальными процедурами разработки REST API важно учитывать эти нюансы типов данных для соблюдения стандартов обмена. Рассмотрим по шагам, как делать правильно.
Если мы формируем JSON вручную через структуру или соответствие, алгоритм максимально прост. Нам достаточно присвоить ключу значение Неопределено. Рассмотрим пример кода:
Данные = Новый Структура;
Данные.Вставить("ИмяОбъекта", "Склад №1");
Данные.Вставить("Описание", Неопределено); // Это запишется как null без кавычек
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, Данные);
Результат = ЗаписьJSON.Закрыть();
// Результат: {"ИмяОбъекта": "Склад №1", "Описание": null}
В этом примере 1С автоматически распознает Неопределено и транслирует его в корректный формат. Подобные базовые приемы входят в фреймворк для интеграции систем 1С без боли и страданий. Если же в переменную попадает именно NULL из запроса, перед вставкой в структуру следует выполнить проверку:
ЗначениеДляЗаписи = ?(ЗначениеИзЗапроса = NULL, Неопределено, ЗначениеИзЗапроса);
Структура.Вставить("Поле", ЗначениеДляЗаписи);
Ситуация усложняется, когда используются XDTO-пакеты. Если в схеме XSD свойство определено как string, то попытка записать туда Неопределено вызовет ошибку отображения типов. Проанализируем, как настроить пакет в конфигураторе, опираясь на примеры валидации и разбора входящих запросов с помощью XDTO и использование флага Nillable:
Истина.xs:string) позволяет принимать пустые значения.После этой настройки программный код будет выглядеть следующим образом:
ТипСклада = ФабрикаXDTO.Тип("http://www.example.com/erp", "Склад");
ОбъектСклад = ФабрикаXDTO.Создать(ТипСклада);
ОбъектСклад.Наименование = "Основной";
ОбъектСклад.Комментарий = Неопределено; // Благодаря флагу "Возможно пустое" запишется null
Запись = Новый ЗаписьJSON();
Запись.УстановитьСтроку();
ФабрикаXDTO.ЗаписатьJSON(Запись, ОбъектСклад);
ТекстJSON = Запись.Закрыть();
Если флаг Возможно пустое не установлен, 1С будет ожидать строку, и передача Неопределено приведет к программному сбою на этапе присвоения значения свойству XDTO.
Рассмотрим более элегантный способ, который позволяет автоматизировать подмену типов для всей выгрузки сразу. Это особенно полезно, когда реализуется надежная выгрузка данных в Google Таблицы через сервисный аккаунт. В методе ЗаписатьJSON предусмотрен параметр НастройкиСериализацииJSON. Используя его, можно внедрить универсальный механизм выгрузки данных через функции-обработчики, которые будут автоматически заменять NULL на Неопределено.
Посмотрим на пример реализации такого обработчика:
Функция ОбработкаЗначенийПередЗаписью(Данные, ДополнительныеПараметры, СтандартнаяОбработка) Экспорт
Если Данные = NULL Тогда
СтандартнаяОбработка = Ложь;
Возврат Неопределено; // Платформа сама запишет null
КонецЕсли;
КонецФункции
// При вызове записи:
Настройки = Новый НастройкиСериализацииJSON;
Настройки.ИмяФункцииОбработчика = "ОбработкаЗначенийПередЗаписью";
ЗаписатьJSON(ЗаписьJSON, МояСтруктура, Настройки);
Этот метод особенно полезен, когда вы выгружаете большие массивы данных, полученные напрямую из запросов. Вам не нужно перебирать каждую строку в цикле — платформа сделает это за вас.
В некоторых случаях принимающая сторона требует, чтобы поле могло быть либо строкой, либо числом, либо null. В XDTO это решается созданием SimpleType с видом Union. Мы можем объединить тип xs:string и какой-либо другой тип. Однако для большинства задач обмена данными через JSON достаточно использования стандартного флага Nillable, так как JSON не так строго типизирован, как XML.
Если по каким-то причинам вы не можете изменить настройки XDTO или структуру данных, можно прибегнуть к текстовой замене. Мы записываем значение как уникальный маркер (строку), а затем заменяем его в готовом файле. Иногда такие "хитрости" требуются, когда вы выполняете получение токена авторизации RuStore с подписью RSA и сталкиваетесь с жесткими требованиями к формату тела запроса.
// 1. Записываем специальную строку
Структура.Вставить("Параметр", "REPLACE_ME_WITH_NULL");
// 2. Сериализуем в строку
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, Структура);
Текст = ЗаписьJSON.Закрыть();
// 3. Выполняем замену кавычек и маркера на null
Текст = СтрЗаменить(Текст, """REPLACE_ME_WITH_NULL""", "null");
Важно: Это решение является "костылем" и должно использоваться только в крайнем случае, так как оно требует осторожности с кавычками и может замедлить работу при очень больших объемах текста.
Проанализировав все способы, мы видим, что наиболее правильным и "чистым" решением является приведение всех значений NULL к Неопределено перед записью и правильная настройка XDTO-пакета с использованием флага Возможно пустое. Это гарантирует, что ваш JSON будет валидным, а принимающая система (API) корректно интерпретирует отсутствие значения.