При разработке HTTP-сервисов на платформе 1С:Предприятие версии 8.3 часто возникает необходимость обмена данными в формате JSON. Одной из распространенных задач является обработка вложенных JSON-объектов, где ключи верхнего уровня содержат не просто значения, а другие объекты со своими свойствами. В этом материале мы подробно рассмотрим, как корректно парсить такой JSON в 1С, как избежать частой ошибки "Поле объекта не обнаружено" и какие есть лучшие практики для работы с JSON.
Рассмотрим типовую ситуацию, когда HTTP-сервис 1С получает вложенный JSON-объект, содержащий информацию о товарах, например, в следующем формате:
{
"Имя": "Иван",
"Телефон": "+79001234567",
"Товары": {
"item1": {
"Артикул": "5051",
"Количество": "2",
"Цена": "599"
},
"item2": {
"Артикул": "6052",
"Количество": "1",
"Цена": "369"
}
}
}
Наша задача – извлечь данные об артикуле, количестве и цене для каждого товара, который находится внутри объекта "Товары".
Прежде чем приступить к обработке, важно понять, как 1С интерпретирует JSON-структуры. Функция ПрочитатьJSON() преобразует JSON-строку в объекты 1С:Предприятия. Ключевые моменты здесь:
Структура.Ключ). В более общем случае, особенно если ключи содержат символы, несовместимые с именами переменных 1С (например, "Артикул"), это будет Соответствие, где доступ к значениям осуществляется по ключу в квадратных скобках (Соответствие["Ключ"]).В нашем примере JSON:
Данные.Товары (доступ через Данные.Товары, если Данные – это результат ПрочитатьJSON()) само по себе является Структурой или Соответствием, поскольку содержит вложенные объекты "item1": {...} и "item2": {...}.item1 и item2 также является Структурой или Соответствием, содержащим ключи "Артикул", "Количество", "Цена".Рассмотрим предложенную в теме функцию, которая пытается обработать полученный JSON:
Функция ТестДжейсонТоварыМетод1(Запрос)
Ответ = Новый HTTPСервисОтвет(200);
ТелоЗапроса = Запрос.ПолучитьТелоКакСтроку;
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(ТелоЗапроса);
Данные = ПрочитатьJSON(ЧтениеJSON);
// Получаем Имя и Телефон
Имя = Данные.Имя;
Телефон = Данные.Телефон;
// Получаем объект "Товары"
Товары = Данные.Товары;
ЧтениеJSON.Закрыть; // Закрываем чтение JSON
Результат = "";
// Начальная попытка итерации
Для Каждого Товар из Товары Цикл
// Здесь возникает ошибка "Поле объекта не обнаружено (Артикул)"
Артикул = Товар["Артикул"];
Количество = Товар["Количество"];
Цена = Товар["Цена"];
Результат = Результат + "Артикул: " + Артикул + " Количество: " + Количество + " Цена: " + Цена + Символы.ПС;
КонецЦикла;
Ответ.УстановитьТелоИзСтроки(Результат);
Возврат Ответ;
КонецФункции
Ошибка "Поле объекта не обнаружено (Артикул)" возникает на строке Артикул = Товар["Артикул"];. Давайте выясним причину. Когда мы пишем Товары = Данные.Товары;, переменная Товары становится структурой, которая содержит элементы с ключами "item1", "item2". При итерации по этой структуре с помощью Для Каждого Товар из Товары Цикл, каждый элемент Товар в цикле будет не самой вложенной структурой (например, `{ "Артикул": "5051", ... }`), а объектом, который содержит в себе два свойства: Ключ (например, "item1") и Значение (именно здесь и находится вложенная структура с Артикулом, Количеством, Ценой).
Таким образом, на первой итерации Товар.Ключ будет равен "item1", а Товар.Значение будет равно структуре { "Артикул": "5051", "Количество": "2", "Цена": "599" }. Соответственно, попытка обратиться к Товар["Артикул"] напрямую проваливается, потому что у самого объекта Товар (который является элементом итерации) нет поля с именем "Артикул", оно находится внутри его свойства Значение.
Для того чтобы правильно получить доступ к артикулу, количеству и цене, нам необходимо сначала обратиться к свойству Значение текущего элемента итерации, а затем уже к нужному полю внутри этой вложенной структуры.
Вот как будет выглядеть исправленный участок кода:
Функция ТестДжейсонТоварыМетод1(Запрос)
Ответ = Новый HTTPСервисОтвет(200);
ТелоЗапроса = Запрос.ПолучитьТелоКакСтроку;
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(ТелоЗапроса);
Данные = ПрочитатьJSON(ЧтениеJSON);
Имя = Данные.Имя;
Телефон = Данные.Телефон;
Товары = Данные.Товары; // Товары - это структура (Соответствие), содержащая item1, item2 и т.д.
ЧтениеJSON.Закрыть();
Результат = "Полученные данные:" + Символы.ПС;
Результат = Результат + "Имя: " + Имя + Символы.ПС;
Результат = Результат + "Телефон: " + Телефон + Символы.ПС;
Результат = Результат + "--- Товары ---" + Символы.ПС;
// Корректная итерация по структуре "Товары"
Для Каждого ЭлементТовараИзСтруктуры Из Товары Цикл
// ЭлементТовараИзСтруктуры имеет свойства Ключ (например, "item1") и Значение (вложенная структура)
// Вложенная структура с данными товара
ВложеннаяСтруктураТовара = ЭлементТовараИзСтруктуры.Значение;
// Доступ к полям внутри вложенной структуры
Артикул = ВложеннаяСтруктураТовара["Артикул"];
Количество = ВложеннаяСтруктураТовара["Количество"];
Цена = ВложеннаяСтруктураТовара["Цена"];
Результат = Результат + " Ключ товара: " + ЭлементТовараИзСтруктуры.Ключ + Символы.ПС;
Результат = Результат + " Артикул: " + Артикул + Символы.ПС;
Результат = Результат + " Количество: " + Количество + Символы.ПС;
Результат = Результат + " Цена: " + Цена + Символы.ПС + Символы.ПС;
КонецЦикла;
Ответ.УстановитьТелоИзСтроки(Результат);
Возврат Ответ;
КонецФункции
Как мы видим, основное изменение заключается в доступе к полям: ВложеннаяСтруктураТовара["Артикул"], где ВложеннаяСтруктураТовара — это ЭлементТовараИзСтруктуры.Значение. Этот подход позволяет правильно извлечь данные из каждой вложенной структуры.
Для более надежной и эффективной работы с JSON в 1С рекомендуем следующие подходы:
ЧтениеJSON и ПрочитатьJSON()Эти встроенные механизмы являются стандартным способом десериализации JSON в 1С. ЧтениеJSON позволяет пошагово читать JSON, а ПрочитатьJSON() — преобразовать всю JSON-строку целиком в объекты 1С (Структура, Соответствие, Массив).
// Пример использования ЧтениеJSON для установки строки
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(ТелоЗапроса);
Данные = ПрочитатьJSON(ЧтениеJSON);
ЧтениеJSON.Закрыть(); // Всегда закрывайте объект ЧтениеJSON после использования
.Свойство()Перед тем как пытаться обратиться к полю по ключу, всегда полезно проверить его существование. Это позволит избежать ошибок "Поле объекта не обнаружено", особенно при работе с внешними системами, которые могут отправлять неполные данные или данные с изменяющейся структурой.
Если ВложеннаяСтруктураТовара.Свойство("Артикул") Тогда
Артикул = ВложеннаяСтруктураТовара["Артикул"];
Иначе
Артикул = Неопределено; // Или обработка отсутствующего поля
КонецЕсли;
При десериализации дат из JSON следует быть внимательными. JSON воспринимает дату как обычную строку. Для корректного преобразования строкового представления даты в формат даты 1С, вы можете использовать параметры функции ПрочитатьJSON(): ИменаСвойствСоЗначениямиДата и ОжидаемыйФорматДаты. Если эти параметры не указаны, вам придется преобразовывать строки в даты вручную, используя, например, Дата(СтрокаДаты).
// Пример с указанием формата даты (если в JSON даты в определенном формате)
// Представьте, что у нас есть JSON вида: { "ДатаДокумента": "2023-10-26T10:30:00" }
// ИменаСвойствСоЗначениямиДата - массив строк с именами свойств, которые содержат даты
// ОжидаемыйФорматДаты - строка, описывающая формат даты (например, "ISO")
ДанныеСДатой = ПрочитатьJSON(ЧтениеJSON, , Новый Массив("ДатаДокумента"), "ISO");
// Теперь ДанныеСДатой.ДатаДокумента будет иметь тип Дата 1С
Начиная с версии 8.3.7.1759, платформа 1С:Предприятие поддерживает сериализацию и десериализацию JSON для любых объектов 1С:Предприятия с использованием СериализаторXDTO. Это более мощный инструмент для работы со сложными и типизированными структурами данных, особенно когда необходимо преобразовывать объекты 1С в JSON и обратно, сохраняя при этом метаданные.
// Пример сериализации объекта 1С в JSON с использованием XDTO
// Запрос = Новый Запрос("ВЫБРАТЬ ...");
// РезультатЗапроса = Запрос.Выполнить().Выгрузить();
// Сериализатор = Новый СериализаторXDTO;
// СтрокаJSON = Сериализатор.ЗаписатьJSON(РезультатЗапроса);
При работе с очень большими JSON-документами, которые могут потреблять много памяти, или при медленных операциях, может быть эффективнее использовать потоковый метод чтения/записи JSON. Для этого можно использовать ЧтениеJSON и ЗаписьJSON в сочетании с файловыми потоками, что позволяет обрабатывать данные по частям, не загружая весь документ в память.
В сообществе 1С существует множество готовых наработок и библиотек, которые предоставляют вспомогательные функции для рекурсивного разбора JSON-объектов любой вложенности в соответствующие структуры 1С (Структура, Соответствие, Массив), делая код более чистым и универсальным.
Таким образом, понимание того, как 1С преобразует JSON-структуры, и правильное использование свойств Ключ и Значение при итерации по структурам, является ключом к успешной обработке вложенных JSON-объектов и предотвращению ошибки "Поле объекта не обнаружено". Используя эти рекомендации, вы сможете создавать более надежные и эффективные HTTP-сервисы и интеграционные решения в 1С.