При интеграции 1С с внешними REST API или веб-сервисами разработчики регулярно сталкиваются с необходимостью разбора (десериализации) входящих строк в формате JSON. Платформа 1С предоставляет для этого удобные встроенные инструменты. Однако стандартные механизмы могут преподнести неприятные сюрпризы, если структура JSON-файла содержит специфические ключи — например, имена свойств с двоеточиями, точками, дефисами или начинающиеся с цифр. В этой статье мы подробно разберем, почему возникает популярная ошибка десериализации, как правильно настроить чтение таких данных и как корректно извлечь значения, даже если ключи заранее неизвестны.
Рассмотрим типичную ситуацию. Нам поступает JSON-строка, в которой одно или несколько свойств имеют имена вида 0:1, @type или user-id. При попытке прочитать эту строку стандартным методом платформа выдает ошибку:
«Недопустимое имя свойства для чтения JSON в объект Структура»
Давайте проанализируем, почему это происходит. По умолчанию метод ПрочитатьJSON() преобразует все объекты JSON во встроенный тип данных 1С — Структура. Ключи структуры в платформе 1С обязаны строго соответствовать правилам именования переменных во встроенном языке. Это значит, что имя свойства структуры:
:), дефис (-), точка (.), собачка (@) и пробелы.Поскольку имя свойства 0:1 содержит двоеточие и начинается с цифры, платформа физически не может создать свойство структуры с таким именем. В результате выполнение кода аварийно завершается.
Чтобы обойти это жесткое ограничение, мы должны указать платформе, что вместо типа Структура необходимо использовать тип Соответствие. В отличие от структур, ключами в соответствиях могут выступать абсолютно любые типы данных, включая строки произвольного формата со спецсимволами.
Разберем, как реализовать этот подход на практике. Для этого в метод ПрочитатьJSON() нужно передать второй параметр — ИспользоватьСоответствие, установив его в значение Истина. Посмотрим на пример кода:
// Создаем объект для чтения JSON
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(СтрокаJSON);
// Читаем данные, явно указав использование Соответствия
РезультатДесериализации = ПрочитатьJSON(ЧтениеJSON, Истина);
ЧтениеJSON.Закрыть();
При таком вызове платформа автоматически и рекурсивно преобразует все вложенные JSON-объекты в коллекцию Соответствие, а JSON-массивы — в привычный тип Массив. Никаких дополнительных ручных обходов для десериализации на этом этапе делать не нужно.
После успешной десериализации разработчики часто сталкиваются со следующей проблемой при попытке обратиться к вложенным данным. Например, конструкция СтруктураОтвета.Получить("images")[0] неожиданно возвращает Неопределено, хотя в отладчике наглядно видно, что коллекция заполнена. Выясним, почему так происходит.
Здесь кроются две важные технические особенности работы с коллекциями в 1С:
1. Строковые ключи вместо числовых индексов
В формате JSON ключи объектов всегда являются строковыми значениями, даже если они выглядят как числа. Если исходный JSON содержал структуру картинок в виде объекта с числовыми именами свойств, например: "images": {"0": "link1", "1": "link2"}, то после десериализации ключами во вложенном соответствии станут строковые значения "0" и "1", а не числа 0 и 1.
Платформа 1С строго различает типы ключей в соответствии. Обращение к элементу по числу 0 вернет Неопределено, потому что ключ "0" (строка) не равен числу 0. Чтобы исправить это, мы должны передавать строковый ключ:
Картинки = СтруктураОтвета.Получить("images");
Если Картинки <> Неопределено Тогда
ПерваяКартинка = Картинки.Получить("0"); // Передаем строковый ключ "0"
КонецЕсли;
2. Объект JSON вместо Массива JSON
Если в исходном тексте JSON данные были заключены в фигурные скобки {} (объект), а не в квадратные [] (массив), то платформа прочитает их как Соответствие. У типа данных Соответствие в 1С нет понятия обращения по порядковому индексу. К нему невозможно обратиться так, как к обычному массиву. Если ключи генерируются динамически на стороне внешнего API и заранее нам неизвестны, мы не сможем прочитать их по фиксированному ключу.
Если API возвращает произвольные ключи (например, идентификаторы объектов или даты), единственным надежным способом получить данные является перебор коллекции в цикле. Давайте посмотрим, как правильно организовать обход полученного соответствия:
Изображения = СтруктураОтвета.Получить("images");
Если ТипЗнч(Изображения) = Тип("Соответствие") Тогда
// Обходим коллекцию в цикле "Для Каждого"
Для Каждого Элемент Из Изображения Цикл
ИмяКлюча = Элемент.Ключ; // Здесь будет наш сложный ключ, например "0:1"
ЗначениеКартинки = Элемент.Значение; // Сами данные
// Выполняем обработку полученных данных
Сообщить("Ключ: " + ИмяКлюча + ", Значение: " + ЗначениеКартинки);
КонецЦикла;
КонецЕсли;
Используя цикл Для Каждого, мы последовательно получаем доступ ко всем элементам соответствия, независимо от того, насколько сложные спецсимволы присутствуют в их ключах.
В некоторых случаях разработчикам критически важно работать именно с типом Структура — например, если вся остальная логика конфигурации завязана на обращение к свойствам через точку (Ответ.images.ИмяСвойства) или если десериализованный объект необходимо передавать в типовые процедуры, жестко ожидающие только структуры. Рассмотрим два альтернативных подхода.
Мы можем обработать исходную JSON-строку перед ее передачей в объект ЧтениеJSON, чтобы заменить все недопустимые спецсимволы в именах свойств на разрешенные (например, на знак подчеркивания _).
Если проблемные ключи нам известны заранее, мы можем использовать простую замену:
// Заменяем двоеточие в конкретном ключе
СтрокаJSON = СтрЗаменить(СтрокаJSON, """0:1""", """Prop_0_1""");
Если же ключи динамические, можно прибегнуть к регулярным выражениям через COM-объект VBScript.RegExp (для Windows-серверов). Это позволит найти все двоеточия или дефисы, расположенные именно в именах свойств (внутри кавычек слева от разделительного двоеточия JSON), и заменить их на безопасные символы. Важно настраивать регулярное выражение аккуратно, чтобы случайно не повредить двоеточия внутри значений (например, в ссылках или датах).
Если файл JSON имеет огромный размер или его структура крайне сложна, чтение всей строки в память может быть нерациональным. В такой ситуации мы можем использовать объект ЧтениеJSON для последовательного перебора элементов «на лету».
Этот метод позволяет перехватывать имена свойств в процессе разбора и подменять их программно перед заполнением результирующей структуры. Проанализируем пример такой реализации:
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(СтрокаJSON);
РезультирующаяСтруктура = Новый Структура;
Пока ЧтениеJSON.Прочитать() Цикл
Если ЧтениеJSON.ТипТекущегоЗначения = ТипЗначенияJSON.ИмяСвойства Тогда
ИмяСвойства = ЧтениеJSON.ТекущееЗначение;
// Если имя свойства содержит недопустимый символ, трансформируем его
Если ИмяСвойства = "0:1" Тогда
ИмяСвойства = "Prop_0_1";
КонецЕсли;
// Читаем следующее значение, соответствующее этому свойству
ЧтениеJSON.Прочитать();
ЗначениеСвойства = ЧтениеJSON.ТекущееЗначение;
// Записываем в структуру уже под очищенным именем
РезультирующаяСтруктура.Вставить(ИмяСвойства, ЗначениеСвойства);
КонецЕсли;
КонецЦикла;
ЧтениеJSON.Закрыть();
Таким образом, мы детально разобрали особенности десериализации нестандартных JSON-строк в 1С. Использование параметра ИспользоватьСоответствие в методе ПрочитатьJSON() является наиболее быстрым, простым и надежным решением проблемы недопустимых символов в именах свойств. А понимание различий между типами ключей и коллекциями поможет вам легко извлекать нужные данные в любых сценариях интеграции.