JSON в 1С 8.3 на практике: разбор ответа сервиса, формирование и обмен данными

· 9 мин

Содержание

Для работы с 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));
    КонецЕсли;

    Возврат РазобратьЗаказ(ТекстОтвета);

КонецФункции

Ключевые моменты:

  1. Таймаут 30 секунд в конструкторе соединения. Без него зависший сервис держит сеанс пользователя неограниченно.
  2. ИспользованиеByteOrderMark.НеИспользовать. Без этого параметра в начало тела может попасть BOM, и строгий сервер ответит ошибкой разбора, хотя JSON корректный.
  3. Кодировку ответа указывайте явно. Если сервер не прислал charset, кириллица превратится в нечитаемые символы.
  4. 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 делает его сам.

Частые ошибки при работе с JSON в 1С

Диагностика: выберите симптом

Частые вопросы

С какой версии платформы в 1С есть встроенная работа с JSON?
Объекты ЧтениеJSON и ЗаписьJSON появились в платформе 8.3.6. В более ранних версиях JSON разбирали самописными функциями или внешними компонентами.
Можно ли работать с JSON на клиенте?
Объекты чтения и записи JSON доступны и на клиенте. Обращения к внешним сервисам, выборки из базы и обработку больших файлов выполняйте на сервере.
Как получить читаемый JSON с отступами для отладки?
Создайте ПараметрыЗаписиJSON с ПереносСтрокJSON.Авто и символом отступа, например Символы.Таб, и передайте их в УстановитьСтроку или ОткрытьФайл.
Как выгрузить таблицу значений в JSON для внешнего сервиса?
Переберите строки и для каждой создайте структуру с нужными колонками, собрав их в массив. СериализаторXDTO тоже запишет таблицу, но в формате, понятном только другой базе 1С.
Почему число 15400.50 пришло как 15400.5?
В JSON у числа нет фиксированной точности, незначащий ноль отбрасывается. Если сервису нужна строка с двумя знаками, передайте сумму строкой через Формат(Сумма, “ЧДЦ=2; ЧРД=.; ЧГ=0”).