JSON в 1С 8.3 на практике: разбор ответа сервиса, формирование и обмен данными
Содержание
Для работы с JSON в 1С 8.3 есть два объекта платформы: ЧтениеJSON разбирает текст, ЗаписьJSON его формирует. Глобальные функции ПрочитатьJSON() и ЗаписатьJSON() за одну строку превращают JSON в Соответствие или Структуру и обратно. Всё это появилось в платформе 8.3.6, внешние компоненты и самописные парсеры больше не нужны.
Для интеграции с внешними сервисами к этим объектам добавляют HTTPСоединение и HTTPЗапрос, а для выгрузки документов и справочников целиком — СериализаторXDTO. Ниже рабочие примеры кода на каждый случай: парсинг, генерация, обмен по HTTP, проверка и обработка больших объёмов.
Чем платформа 1С работает с JSON
Набор объектов небольшой, и у каждого своя задача.
| Объект или функция | Для чего | Когда брать |
|---|---|---|
ЧтениеJSON | Последовательное чтение текста или файла | Источник для ПрочитатьJSON() и потоковый разбор |
ЗаписьJSON | Формирование текста или файла | Приёмник для ЗаписатьJSON() и ручная запись по элементам |
ПрочитатьJSON() | Весь JSON сразу в коллекции 1С | Ответы API до нескольких мегабайт |
ЗаписатьJSON() | Коллекции 1С сразу в JSON | Тело запроса, файлы настроек |
НастройкиСериализацииJSON | Формат дат, запись массивов | Когда сервис ждёт даты в определённом виде |
ПараметрыЗаписиJSON | Переносы строк, отступы, экранирование | Компактный или читаемый вывод |
СериализаторXDTO | Объекты конфигурации в JSON и обратно | Обмен между базами 1С |
Какие типы 1С ЗаписатьJSON() переводит без помощи:
- 📦
Структура,ФиксированнаяСтруктура,Соответствие→ объект JSON; - 📋
Массив,ФиксированныйМассив→ массив JSON; - 🔤
Строка,Число,Булево→ одноимённые типы JSON; - 📅
Дата→ строка в формате из настроек сериализации; - ⭕
Неопределено→null.
Ссылки, ТаблицаЗначений, ДеревоЗначений и объекты справочников напрямую не записываются. Для них есть функция преобразования или СериализаторXDTO, об этом ниже.
Как разобрать JSON в 1С: строка, файл, структура или соответствие
Пусть сервис вернул заказ:
{
"order-id": "А-125",
"created_at": "2026-03-14T10:25:00",
"total": 15400.5,
"items": [
{"sku": "1001", "qty": 2, "price": 4200},
{"sku": "1007", "qty": 1, "price": 7000.5}
]
}
Разбор в одну функцию:
Функция РазобратьЗаказ(ТекстJSON) Экспорт
Чтение = Новый ЧтениеJSON;
Чтение.УстановитьСтроку(ТекстJSON);
// Истина — объекты JSON читаются в Соответствие,
// "created_at" — имя свойства, которое сразу станет датой
Данные = ПрочитатьJSON(Чтение, Истина, "created_at", ФорматДатыJSON.ISO);
Чтение.Закрыть();
Возврат Данные;
КонецФункции
Дальше значения берут по ключу:
Заказ = РазобратьЗаказ(ТекстОтвета);
НомерЗаказа = Заказ["order-id"];
СуммаЗаказа = Заказ["total"];
Для Каждого Позиция Из Заказ["items"] Цикл
Сумма = Позиция["qty"] * Позиция["price"]; // 2 * 4200 = 8400, 1 * 7000.5 = 7000.5
КонецЦикла;
Массив JSON всегда приходит как Массив, вложенные объекты — как Соответствие или Структура, в зависимости от второго параметра.
Структура или соответствие
Второй параметр ПрочитатьJSON() решает больше, чем кажется.
| Вариант | Плюсы | Ограничения |
|---|---|---|
Структура (по умолчанию) | Обращение через точку: Данные.total | Ключ обязан быть идентификатором 1С. order-id, 1c_code, ключ с пробелом вызовут исключение |
Соответствие (Истина) | Принимает любые ключи | Обращение только через ["ключ"] или Получить() |
Для ответов чужих сервисов всегда читайте в Соответствие. Сегодня ключи латиницей без дефисов, а завтра поставщик добавит delivery-date, и разбор упадёт на рабочей базе.
Даты и файлы
Даты в JSON — обычные строки. Чтобы получить тип Дата, перечислите такие свойства в третьем параметре (строкой через запятую или массивом). Одиночную строку переводит функция ПрочитатьДатуJSON(Строка, ФорматДатыJSON.ISO).
Файл читается так же, только вместо УстановитьСтроку() вызывают Чтение.ОткрытьФайл(ИмяФайла). Кодировку по умолчанию платформа определяет сама, UTF-8 с BOM и без BOM читаются одинаково.
Генерация JSON в 1С: из коллекций и по элементам
Самый короткий путь — собрать Структуру и передать в ЗаписатьJSON():
Функция ТелоЗаказаJSON(НомерЗаказа, Позиции) Экспорт
Данные = Новый Структура;
Данные.Вставить("number", НомерЗаказа);
Данные.Вставить("date", ТекущаяДатаСеанса());
Данные.Вставить("items", Позиции); // Массив структур "sku, qty"
Параметры = Новый ПараметрыЗаписиJSON(ПереносСтрокJSON.Нет);
Настройки = Новый НастройкиСериализацииJSON;
Настройки.ФорматСериализацииДаты = ФорматДатыJSON.ISO;
Настройки.ВариантЗаписиДаты = ВариантЗаписиДатыJSON.ЛокальнаяДата;
Запись = Новый ЗаписьJSON;
Запись.УстановитьСтроку(Параметры);
ЗаписатьJSON(Запись, Данные, Настройки);
Возврат Запись.Закрыть(); // при УстановитьСтроку() Закрыть() возвращает текст
КонецФункции
Пояснения к настройкам:
ПереносСтрокJSON.Нет— JSON в одну строку, для тела запроса. Для отладки беритеПереносСтрокJSON.Авто, вторым параметром можно передать символ отступа, напримерСимволы.Таб.ВариантЗаписиДатыJSONзадаёт, писать дату как локальную, локальную со смещением или универсальную (UTC). Сервисы с часовыми поясами обычно ждут вариант со смещением.ФорматДатыJSONбываетISO,JavaScriptиMicrosoft. ISO понимают почти все.
Ссылки и неподдерживаемые типы
Если в структуре окажется ссылка на номенклатуру, ЗаписатьJSON() выдаст исключение. Вместо ручного обхода данных подключите функцию преобразования. Платформа вызывает её только для значений, которые сама записать не может:
// В общем модуле ИнтеграцияJSON (серверный)
Функция ПреобразоватьЗначение(Свойство, Значение, ДополнительныеПараметры, Отказ) Экспорт
Если ТипЗнч(Значение) = Тип("СправочникСсылка.Номенклатура") Тогда
Возврат Строка(Значение.УникальныйИдентификатор());
КонецЕсли;
Отказ = Истина; // всё остальное пропускаем, без исключения
Возврат Неопределено;
КонецФункции
// Вызов
ЗаписатьJSON(Запись, Данные, Настройки, "ПреобразоватьЗначение", ИнтеграцияJSON);
Функция должна быть экспортной, а модуль передаётся четвёртым-пятым параметрами: имя функции строкой и сам модуль.
Потоковая запись
Для выгрузки тысяч строк не собирайте огромный массив структур. Пишите элементы прямо из выборки:
Запись = Новый ЗаписьJSON;
Запись.ОткрытьФайл(ИмяФайла, "UTF-8");
Запись.ЗаписатьНачалоМассива();
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Запись.ЗаписатьНачалоОбъекта();
Запись.ЗаписатьИмяСвойства("code");
Запись.ЗаписатьЗначение(Выборка.Код);
Запись.ЗаписатьИмяСвойства("name");
Запись.ЗаписатьЗначение(Выборка.Наименование);
Запись.ЗаписатьКонецОбъекта();
КонецЦикла;
Запись.ЗаписатьКонецМассива();
Запись.Закрыть();
Памяти уходит столько, сколько занимает одна строка выборки, а не весь результат.
Сериализация объектов 1С в JSON через СериализаторXDTO
Когда нужно передать в другую базу 1С документ целиком, с табличными частями и ссылками, ручная сборка структур — лишняя работа. СериализаторXDTO записывает любой объект конфигурации, ссылку, ТаблицуЗначений и ХранилищеЗначения.
// Выгрузка
Объект = ДокументСсылка.ПолучитьОбъект();
Запись = Новый ЗаписьJSON;
Запись.УстановитьСтроку();
СериализаторXDTO.ЗаписатьJSON(Запись, Объект, НазначениеТипаXML.Явное);
ТекстJSON = Запись.Закрыть();
// Загрузка в базе-приёмнике
Чтение = Новый ЧтениеJSON;
Чтение.УстановитьСтроку(ТекстJSON);
ПолученныйОбъект = СериализаторXDTO.ПрочитатьJSON(Чтение);
Чтение.Закрыть();
В тексте каждое значение лежит парой #type и #value: тип из метаданных и данные. Ссылки записываются уникальными идентификаторами.
Что учесть до внедрения:
- 🔗 обе базы должны иметь одинаковые объекты метаданных, иначе чтение упадёт на неизвестном типе;
- 🆔 прочитанный объект сохраняет GUID источника, и
Записать()создаст элемент с той же ссылкой либо перезапишет существующий; - 🌐 внешний сервис формат
#type/#valueне поймёт, для чужих API собирайте структуры вручную.
Перед загрузкой объектов из другой базы в рабочую сделайте резервную копию. Для загрузки без проверок заполнения и проведения обычно ставят Объект.ОбменДанными.Загрузка = Истина, а это значит, что ошибочные данные запишутся без контроля.
Для объектов XDTO, построенных по пакету (ОбъектXDTO), есть похожая пара методов ФабрикаXDTO.ЗаписатьJSON() и ФабрикаXDTO.ПрочитатьJSON(). Это вариант для интеграций по заранее описанной схеме.
Обмен JSON с REST API через HTTP-запросы
Типовая отправка заказа во внешний сервис. Код выполняется на сервере:
Функция ОтправитьЗаказ(ТекстJSON, Токен) Экспорт
Соединение = Новый HTTPСоединение("api.example.ru", 443, , , , 30,
Новый ЗащищенноеСоединениеOpenSSL);
Заголовки = Новый Соответствие;
Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
Заголовки.Вставить("Accept", "application/json");
Заголовки.Вставить("Authorization", "Bearer " + Токен);
Запрос = Новый HTTPЗапрос("/v1/orders", Заголовки);
Запрос.УстановитьТелоИзСтроки(ТекстJSON, КодировкаТекста.UTF8,
ИспользованиеByteOrderMark.НеИспользовать);
Ответ = Соединение.ОтправитьДляОбработки(Запрос); // POST
ТекстОтвета = Ответ.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);
Если Ответ.КодСостояния <> 200 И Ответ.КодСостояния <> 201 Тогда
ВызватьИсключение СтрШаблон("Сервис вернул код %1: %2",
Ответ.КодСостояния, Лев(ТекстОтвета, 500));
КонецЕсли;
Возврат РазобратьЗаказ(ТекстОтвета);
КонецФункции
Ключевые моменты:
- Таймаут
30секунд в конструкторе соединения. Без него зависший сервис держит сеанс пользователя неограниченно. ИспользованиеByteOrderMark.НеИспользовать. Без этого параметра в начало тела может попасть BOM, и строгий сервер ответит ошибкой разбора, хотя JSON корректный.- Кодировку ответа указывайте явно. Если сервер не прислал
charset, кириллица превратится в нечитаемые символы. - HTTP-методы:
Получить()— GET,ОтправитьДляОбработки()— POST,Записать()— PUT,Удалить()— DELETE. Для PATCH естьВызватьHTTPМетод("PATCH", Запрос).
Токен и адрес сервиса храните в константе или регистре сведений с ограниченными правами, а не в коде модуля. Код видят все, у кого есть доступ к конфигуратору.
Приём JSON в самой 1С
Если внешняя система сама шлёт данные в 1С, в конфигураторе создают HTTP-сервис: ветка Общие → HTTP-сервисы. В обработчике метода тело берут через Запрос.ПолучитьТелоКакСтроку(), разбирают той же ПрочитатьJSON(), а ответ возвращают объектом HTTPСервисОтвет с кодом и телом JSON. Сервис работает после публикации базы на веб-сервере.
Проверка JSON и обработка ошибок разбора
Чужой JSON может прийти битым, пустым или с другой структурой. Разбор и проверку оборачивают в Попытка:
Попытка
Данные = РазобратьЗаказ(ТекстОтвета);
Исключение
ЗаписьЖурналаРегистрации("Интеграция.Заказы", УровеньЖурналаРегистрации.Ошибка, , ,
ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
ВызватьИсключение "Сервис вернул некорректный JSON, подробности в журнале регистрации";
КонецПопытки;
Синтаксически верный JSON ещё не значит правильные данные. Проверьте структуру до записи в базу:
Функция ЗаказКорректен(Данные, Ошибки) Экспорт
Если ТипЗнч(Данные) <> Тип("Соответствие") Тогда
Ошибки.Добавить("Корень ответа — не объект JSON");
Возврат Ложь;
КонецЕсли;
Для Каждого ИмяПоля Из СтрРазделить("order-id,total,items", ",") Цикл
Если Данные.Получить(ИмяПоля) = Неопределено Тогда
Ошибки.Добавить("Нет поля или оно пустое: " + ИмяПоля);
КонецЕсли;
КонецЦикла;
Если ТипЗнч(Данные["total"]) <> Тип("Число") Тогда
Ошибки.Добавить("Поле total должно быть числом");
КонецЕсли;
Если ТипЗнч(Данные["items"]) <> Тип("Массив") Тогда
Ошибки.Добавить("Поле items должно быть массивом");
КонецЕсли;
Возврат Ошибки.Количество() = 0;
КонецФункции
Получить() возвращает Неопределено и для отсутствующего ключа, и для null. Если эти случаи нужно различать, проверяйте ключ перебором соответствия.
Что ещё стоит логировать: код ответа, первые 500 символов тела и идентификатор объекта. Полное тело с персональными данными в журнал не пишите.
Большие объёмы JSON: память и скорость
ПрочитатьJSON() строит в памяти всю структуру. Ответ на 200 МБ превратится в коллекции, которые займут в несколько раз больше, а рабочий процесс сервера может упереться в лимит памяти.
Приём ответа в файл и потоковый разбор
Сначала ответ сохраняют во временный файл, вторым параметром Получить():
ИмяФайла = ПолучитьИмяВременногоФайла("json");
Ответ = Соединение.Получить(Запрос, ИмяФайла);
Затем читают элементы корневого массива по одному:
Чтение = Новый ЧтениеJSON;
Чтение.ОткрытьФайл(ИмяФайла);
Чтение.Прочитать(); // начало корневого массива
Пока Чтение.Прочитать()
И Чтение.ТипТекущегоЗначения = ТипЗначенияJSON.НачалоОбъекта Цикл
Элемент = ПрочитатьJSON(Чтение, Истина); // читается только этот объект
ОбработатьЭлемент(Элемент);
КонецЦикла;
Чтение.Закрыть();
УдалитьФайлы(ИмяФайла);
В памяти одновременно живёт один элемент, а не весь массив.
Что ещё ускоряет обмен
- 🚫 Не делайте запрос к базе на каждый элемент JSON. Соберите артикулы в массив и найдите номенклатуру одним запросом с условием
В (&Артикулы). - 📄 Берите данные у сервиса постранично, если API поддерживает
limitиoffsetили курсор. 1000 записей за запрос обрабатывать проще, чем 100 000. - 🧱 Записывайте объекты пачками в отдельных транзакциях. Одна транзакция на весь файл держит блокировки долго и при сбое откатывает всё.
- ✂️ Не склеивайте JSON строками через
+. Кроме скорости, ручная склейка ломает экранирование кавычек и переносов, аЗаписьJSONделает его сам.