Почему 1С записывает 'Неопределено' в JSON, а 'Null' вызывает ошибку?

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

При работе с обменами данными в формате JSON разработчики 1С часто сталкиваются с неочевидным, на первый взгляд, поведением системы. Попытка записать в JSON структуру, содержащую значение типа Null, приводит к ошибке, в то время как значение Неопределено обрабатывается корректно и преобразуется в null. Это расходится с интуитивным ожиданием, ведь именно null является стандартным типом для JSON, а undefined (аналог Неопределено) в стандарте отсутствует.

Давайте разберемся, почему платформа "1С:Предприятие" реализована именно так, в чем разница между этими типами и как правильно готовить данные для сериализации.

Стандарт JSON и типы данных в 1С: в чем разница?

Для начала проанализируем теоретическую базу. Стандарт JSON (описанный в RFC 8259) строго определяет список допустимых типов значений:

  1. Строка (string)
  2. Число (number)
  3. Логическое значение (true или false)
  4. Массив (array)
  5. Объект (object, аналог Структуры или Соответствия в 1С)
  6. Специальное значение null для обозначения отсутствия значения

Как мы видим, в этом стандарте нет типа "undefined". В то же время в платформе 1С существуют два разных типа для обозначения "пустых" или отсутствующих значений:

Именно эта разница в семантике и является ключом к пониманию логики сериализации в 1С.

Логика преобразования в JSON, принятая в 1С

Разработчики платформы "1С:Предприятие" сопоставили внутренние типы данных с типами стандарта JSON следующим образом:

1. Неопределено из 1С преобразуется в null в JSON.

Это логичное и правильное решение. Поскольку Неопределено в 1С — это основной способ указать на отсутствие значения в бизнес-логике, его сопоставили с единственным аналогичным по смыслу типом в JSON — null. Это поведение официально задокументировано. Например, в руководстве разработчика прямо указано: "Неопределено – сериализуется в null".

2. Null из 1С не поддерживается для прямой записи в JSON.

Попытка сериализовать структуру или массив, где хотя бы одно из значений имеет тип Null, вызовет ошибку "Передано значение недопустимого типа". Почему так сделано? Тип Null в 1С не является общеупотребительным "пустым" значением. Это узкоспециализированный тип для результатов взаимодействия с СУБД. Исключив его из автоматической сериализации, разработчики платформы предотвращают потенциальную неоднозначность и ошибки при обмене данными с внешними системами, которые не ожидают такой специфики.

В Синтакс-Помощнике, в описании метода ЗаписатьJSON(), можно найти полный список поддерживаемых типов. Важно обратить внимание на примечание, в котором явно указан тип Неопределено, но отсутствует Null.

Практический пример и решение проблемы

Рассмотрим на простом примере, как это работает на практике. Допустим, у нас есть две структуры, одна с Неопределено, другая с Null.

Корректный код, который отработает без ошибок:


СтруктураДляJSON = Новый Структура;
СтруктураДляJSON.Вставить("РабочееЗначение", "Какой-то текст");
СтруктураДляJSON.Вставить("НеопределенноеЗначение", Неопределено);

// Этот код выполнится успешно
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, СтруктураДляJSON);
Результат = ЗаписьJSON.Закрыть();

// В переменной 'Результат' будет строка:
// {"РабочееЗначение":"Какой-то текст","НеопределенноеЗначение":null}
Сообщить(Результат);

Код, который вызовет ошибку:


СтруктураСОшибкой = Новый Структура;
СтруктураСОшибкой.Вставить("РабочееЗначение", "Какой-то текст");
СтруктураСОшибкой.Вставить("NullЗначение", Null); // Проблемное значение

// Этот код вызовет исключение
Попытка
    ЗаписьJSON = Новый ЗаписьJSON;
    ЗаписьJSON.УстановитьСтроку();
    ЗаписатьJSON(ЗаписьJSON, СтруктураСОшибкой);
    Результат = ЗаписьJSON.Закрыть();
Исключение
    // Будет выведено сообщение:
    // "Ошибка при вызове метода контекста (ЗаписатьJSON): Передано значение недопустимого типа"
    Сообщить(ОписаниеОшибки());
КонецПопытки;

Как правильно обрабатывать данные перед записью в JSON?

Главное правило — перед сериализацией необходимо подготовить данные. Если ваши данные получены из запроса к базе данных, они могут содержать значения типа Null. Их нужно явно заменить на Неопределено.

Посмотрим на пример обработки результата запроса:


// Допустим, у нас есть результат запроса
РезультатЗапроса = Запрос.Выполнить().Выгрузить();
МассивДляJSON = Новый Массив;

// Обходим строки результата и формируем массив структур для сериализации
Для Каждого СтрокаТЗ Из РезультатЗапроса Цикл
    СтруктураСтроки = Новый Структура;
    Для Каждого Колонка Из РезультатЗапроса.Колонки Цикл
        ЗначениеПоля = СтрокаТЗ[Колонка.Имя];
        
        // Ключевой момент: заменяем Null на Неопределено
        Если ТипЗнч(ЗначениеПоля) = Тип("Null") Тогда
            СтруктураСтроки.Вставить(Колонка.Имя, Неопределено);
        Иначе
            СтруктураСтроки.Вставить(Колонка.Имя, ЗначениеПоля);
        КонецЕсли;
        
    КонецЦикла;
    МассивДляJSON.Добавить(СтруктураСтроки);
КонецЦикла;

// Теперь этот массив можно безопасно записывать в JSON
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, МассивДляJSON);
РезультатJSON = ЗаписьJSON.Закрыть();

Такой подход гарантирует, что все отсутствующие значения в вашей структуре данных будут корректно преобразованы в стандартное для JSON значение null.

В итоге, можно сделать следующие выводы:

← На главную