Запись и чтение JSON во встроенном языке 1С 8.3
Содержание
Сформировать JSON в 1С проще всего так: собрать данные в Структура, Соответствие и Массив, а затем вызвать ЗаписатьJSON() с объектом ЗаписьJSON, открытым в строку или файл. Если нужен полный контроль над каждым свойством или поток в большой файл, JSON пишут вручную методами ЗаписатьНачалоОбъекта(), ЗаписатьИмяСвойства(), ЗаписатьЗначение().
Оба механизма есть в платформе начиная с 8.3.6. Для обмена между двумя базами 1С есть третий путь — СериализаторXDTO.ЗаписатьJSON(): он сохраняет типы и ссылки, но внешним системам такой формат обычно не подходит. Ниже — код для каждого случая, разбор входящих данных и ошибки, на которых спотыкаются чаще всего.
Три способа сформировать JSON в 1С: какой когда выбрать
Выбор зависит от того, кто будет читать результат и насколько большой объём данных.
| Способ | Когда выбирать | Ограничения |
|---|---|---|
ЗаписьJSON + ручные методы | Поток в файл на сотни мегабайт, нестандартный порядок свойств, частичная запись | Много кода, легко забыть закрыть объект или массив |
ЗаписатьJSON() из коллекций | REST API, веб-сервисы, обмен с сайтом, маркетплейсами | Пишет только примитивы и коллекции; ссылки и перечисления надо преобразовать |
СериализаторXDTO.ЗаписатьJSON() | Обмен 1С ↔ 1С с одинаковыми метаданными | Формат со служебными полями #type и #value, внешней системе он непонятен |
💡 На практике 9 задач из 10 закрывает второй способ. Ручная запись нужна, когда данные не помещаются в память целиком.
Типы, которые JSON понимает без преобразований:
- 🔤
Строка→ строка в кавычках; - 🔢
Число→ число без разделителей разрядов; - ✅
Булево→true/false; - 📅
Дата→ строка в формате ISO, например"2026-10-07T14:30:00"; - ⭕
НеопределеноиNull→null; - 📦
Структура,Соответствие(ключи — строки) → объект{}; - 📚
Массиви фиксированные коллекции → массив[].
Всё остальное — ссылки, перечисления, ТаблицаЗначений, УникальныйИдентификатор, ДвоичныеДанные — ЗаписатьJSON() без подготовки не запишет.
Как записать JSON вручную через объект ЗаписьJSON
Объект ЗаписьJSON работает как курсор: вы по очереди открываете объект, пишете имя свойства, значение, закрываете объект. Результат уходит в строку или в файл.
Запись в строку
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписьJSON.ЗаписатьНачалоОбъекта();
ЗаписьJSON.ЗаписатьИмяСвойства("number");
ЗаписьJSON.ЗаписатьЗначение("00-000125");
ЗаписьJSON.ЗаписатьИмяСвойства("sum");
ЗаписьJSON.ЗаписатьЗначение(15400.50);
ЗаписьJSON.ЗаписатьИмяСвойства("paid");
ЗаписьJSON.ЗаписатьЗначение(Ложь);
ЗаписьJSON.ЗаписатьКонецОбъекта();
ТекстJSON = ЗаписьJSON.Закрыть();
Метод Закрыть() при записи в строку возвращает готовый текст:
{
"number": "00-000125",
"sum": 15400.5,
"paid": false
}
Запись в файл
Вместо УстановитьСтроку() вызывают ОткрытьФайл() с именем файла и кодировкой:
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.ОткрытьФайл("C:\Exchange\orders.json", "UTF-8");
// ... те же вызовы ЗаписатьНачалоОбъекта / ЗаписатьИмяСвойства ...
ЗаписьJSON.Закрыть();
У ОткрытьФайл() есть параметр, отвечающий за метку BOM в начале файла. Часть внешних парсеров на BOM падает, поэтому, если получатель жалуется на «невалидный JSON» при внешне правильном тексте, первым делом проверьте его.
Параметры записи: отступы и экранирование
Внешний вид текста задают через ПараметрыЗаписиJSON. Компактная строка без переносов — частое требование API, где важен размер запроса:
Параметры = Новый ПараметрыЗаписиJSON(ПереносСтрокJSON.Нет);
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку(Параметры);
Для отладки, наоборот, удобен ПереносСтрокJSON.Авто и отступ табуляцией или пробелами — второй параметр конструктора. Остальные параметры управляют экранированием: угловых скобок, амперсанда, слеша, символов вне ASCII. Если в данных HTML или текст будет вставлен в веб-страницу, экранирование угловых скобок включите.
Вложенные объекты и массивы в JSON
Реальный запрос к API — это почти всегда объект с массивом внутри: заказ и его строки, контрагент и его счета.
Вручную, через пары «начало — конец»
ЗаписьJSON.ЗаписатьНачалоОбъекта();
ЗаписьJSON.ЗаписатьИмяСвойства("order");
ЗаписьJSON.ЗаписатьЗначение("00-000125");
ЗаписьJSON.ЗаписатьИмяСвойства("items");
ЗаписьJSON.ЗаписатьНачалоМассива();
Для Каждого Строка Из Товары Цикл
ЗаписьJSON.ЗаписатьНачалоОбъекта();
ЗаписьJSON.ЗаписатьИмяСвойства("sku");
ЗаписьJSON.ЗаписатьЗначение(Строка.Артикул);
ЗаписьJSON.ЗаписатьИмяСвойства("qty");
ЗаписьJSON.ЗаписатьЗначение(Строка.Количество);
ЗаписьJSON.ЗаписатьКонецОбъекта();
КонецЦикла;
ЗаписьJSON.ЗаписатьКонецМассива();
ЗаписьJSON.ЗаписатьКонецОбъекта();
Каждому ЗаписатьНачалоОбъекта() нужен свой ЗаписатьКонецОбъекта(), каждому ЗаписатьНачалоМассива() — ЗаписатьКонецМассива(). Платформа следит за порядком и выдаёт исключение, если, например, записать значение без имени свойства внутри объекта.
Через коллекции: тот же результат короче
Заказ = Новый Структура;
Заказ.Вставить("order", "00-000125");
Заказ.Вставить("date", ТекущаяДатаСеанса());
Строки = Новый Массив;
Для Каждого Строка Из Товары Цикл
Позиция = Новый Структура("sku, qty, price");
Позиция.sku = Строка.Артикул;
Позиция.qty = Строка.Количество;
Позиция.price = Строка.Цена;
Строки.Добавить(Позиция);
КонецЦикла;
Заказ.Вставить("items", Строки);
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, Заказ);
ТекстJSON = ЗаписьJSON.Закрыть();
Когда ключ свойства — не идентификатор 1С (user-id, 1c_code, @type), Структура не подойдёт: ключ с дефисом или цифрой в начале в неё не вставить. Используйте Соответствие:
Данные = Новый Соответствие;
Данные.Вставить("user-id", 4512);
Данные.Вставить("1c_code", "000000017");
Пустой массив запишется как [], пустая структура — как {}. Если API требует, чтобы пустое поле вообще отсутствовало, не вставляйте ключ в коллекцию.
ЗаписатьJSON: как конвертировать ссылки, даты и таблицы
Главная боль при выгрузке объектов 1С — ссылки на справочники и документы. Есть три рабочих приёма.
Приём 1. Подготовить данные заранее
Перед записью превратите ссылку в то, что нужно получателю:
- 🆔 GUID —
XMLСтрока(Ссылка)илиСтрока(Ссылка.УникальныйИдентификатор()); - 🏷️ код или наименование —
Ссылка.Код,Ссылка.Наименование(в запросе лучше выбрать поле сразу, а не обращаться через точку в цикле); - 📋 значение перечисления —
XMLСтрока(ЗначениеПеречисления)вернёт имя значения из метаданных, а не синоним.
ТаблицаЗначений в JSON не пишется. Её обходят циклом и складывают строки в массив структур, как в примере выше.
Приём 2. Функция преобразования
Если структура данных глубокая и готовить каждое поле неудобно, передайте в ЗаписатьJSON() имя экспортной функции, которая вызывается для значений неподдерживаемых типов:
ЗаписатьJSON(ЗаписьJSON, Данные, , "ПреобразоватьДляJSON", ЭтотОбъект);
Функция ПреобразоватьДляJSON(Свойство, Значение, ДополнительныеПараметры, Отказ) Экспорт
Если ОбщегоНазначения.ЭтоСсылка(ТипЗнч(Значение)) Тогда
Возврат XMLСтрока(Значение);
КонецЕсли;
Отказ = Истина; // прочее не пишем
КонецФункции
Четвёртый параметр — имя функции, пятый — модуль, где она лежит (модуль формы или объекта через ЭтотОбъект, либо общий модуль). Проверка ОбщегоНазначения.ЭтоСсылка() есть в типовых конфигурациях на БСП; в своей конфигурации проверьте тип иначе, например через Справочники.ТипВсеСсылки().СодержитТип().
Приём 3. СериализаторXDTO для обмена 1С ↔ 1С
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
СериализаторXDTO.ЗаписатьJSON(ЗаписьJSON, ДокументОбъект, НазначениеТипаXML.Явное);
ТекстJSON = ЗаписьJSON.Закрыть();
На выходе — объект с полями #type и #value, по которым другая база с теми же метаданными восстановит объект через СериализаторXDTO.ПрочитатьJSON(). Для сайта или чужого API этот формат избыточен.
Выгрузка результата запроса в JSON
Типовая задача — отдать список документов или остатков. Схема: запрос выбирает уже готовые для JSON поля, цикл по выборке складывает их в массив структур.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Код КАК code,
| Номенклатура.Наименование КАК name,
| Номенклатура.Артикул КАК sku
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| НЕ Номенклатура.ЭтоГруппа";
Результат = Новый Массив;
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Элемент = Новый Структура("code, name, sku");
ЗаполнитьЗначенияСвойств(Элемент, Выборка);
Результат.Добавить(Элемент);
КонецЦикла;
Приём в том, что псевдонимы полей в запросе (КАК code) совпадают с ключами структуры. Тогда ЗаполнитьЗначенияСвойств() переносит все значения одной строкой, и не нужно присваивать каждое поле вручную. Если в выборке есть ссылка, выберите в запросе её код или наименование, а GUID получите через XMLСтрока() уже в цикле.
Даты: формат и часовой пояс
По умолчанию дата пишется в ISO без смещения. Чтобы передать дату в UTC или со смещением, задайте НастройкиСериализацииJSON:
Настройки = Новый НастройкиСериализацииJSON;
Настройки.ФорматСериализацииДаты = ФорматДатыJSON.ISO;
Настройки.ВариантЗаписиДаты = ВариантЗаписиДатыJSON.ЛокальнаяДатаСоСмещением;
ЗаписатьJSON(ЗаписьJSON, Данные, Настройки);
Кроме ISO, доступны форматы JavaScript и Microsoft — их требуют старые .NET-сервисы.
Чтение и разбор JSON в 1С
Входящий JSON читают тоже двумя способами: целиком в коллекции или потоком.
Целиком: ПрочитатьJSON
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(ТекстОтвета);
Данные = ПрочитатьJSON(ЧтениеJSON, Истина);
ЧтениеJSON.Закрыть();
Для Каждого Позиция Из Данные["items"] Цикл
Артикул = Позиция["sku"];
КонецЦикла;
Второй параметр Истина — читать объекты в Соответствие. Без него объекты превращаются в Структура, и первый же ключ вида order-id вызовет исключение. Для данных из внешних систем всегда читайте в Соответствие: формат ключей там вам не гарантирован.
Даты в JSON — просто строки, и 1С не знает, что "2026-10-07T14:30:00" надо превратить в Дата. Перечислите такие свойства в третьем параметре ПрочитатьJSON() (массив имён) и укажите формат дат в четвёртом — тогда они придут типом Дата. Альтернатива — конвертировать вручную через ПрочитатьДатуJSON(Строка, ФорматДатыJSON.ISO).
Значение null после чтения становится Неопределено. Проверяйте его до обращения к вложенным полям.
Потоком: ЧтениеJSON.Прочитать()
Для файлов на десятки мегабайт читать всё в память неэкономно. Курсорное чтение обходит текст по элементам:
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.ОткрытьФайл("C:\Exchange\prices.json");
Пока ЧтениеJSON.Прочитать() Цикл
Если ЧтениеJSON.ТипТекущегоЗначения = ТипЗначенияJSON.ИмяСвойства
И ЧтениеJSON.ТекущееЗначение = "price" Тогда
ЧтениеJSON.Прочитать();
Цена = ЧтениеJSON.ТекущееЗначение;
// обработать цену
КонецЕсли;
КонецЦикла;
ЧтениеJSON.Закрыть();
ТипТекущегоЗначения принимает значения НачалоОбъекта, КонецОбъекта, НачалоМассива, КонецМассива, ИмяСвойства, Строка, Число, Булево, Null, Комментарий, Ничего. Комбинированный приём для больших массивов: доходите курсором до начала нужного массива, а каждый его элемент читаете ПрочитатьJSON(ЧтениеJSON) — функция заберёт ровно один объект и оставит курсор за ним.
Ошибки при формировании JSON в 1С и как их исправить
Отдельная ловушка — значение реквизита составного типа. Сегодня в нём строка, завтра пользователь выбрал ссылку, и выгрузка падает. Для таких полей функция преобразования надёжнее подготовки «на глаз».
Практики: скорость, размер и обмен по HTTP
Отправка JSON во внешнее API
Соединение = Новый HTTPСоединение("api.example.ru", 443, , , , 30,
Новый ЗащищенноеСоединениеOpenSSL);
Запрос = Новый HTTPЗапрос("/v1/orders");
Запрос.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
Запрос.УстановитьТелоИзСтроки(ТекстJSON, "UTF-8",
ИспользованиеByteOrderMark.НеИспользовать);
Ответ = Соединение.ОтправитьДляОбработки(Запрос);
Если Ответ.КодСостояния = 200 Тогда
ТекстОтвета = Ответ.ПолучитьТелоКакСтроку("UTF-8");
КонецЕсли;
Заголовок Content-Type многие сервисы проверяют строго: без него тело может не разобраться.
Что ускоряет выгрузку
- ⚡ Получайте данные одним запросом сразу с нужными полями (артикул, код, наименование). Обращение через точку к реквизиту ссылки в цикле каждый раз читает объект из базы.
- 🧱 Не собирайте JSON конкатенацией строк. Кавычки, переносы и обратные слеши в данных сломают текст, а экранирование
ЗаписьJSONделает сама. - 📁 Больше 50–100 тысяч строк — пишите потоком в файл ручными методами, а не строите огромную коллекцию в памяти.
- 🗜️ Для API выключайте переносы (
ПереносСтрокJSON.Нет): на больших выгрузках это заметно уменьшает размер.
Где выполнять код
ЗаписьJSON, ЧтениеJSON и функции ЗаписатьJSON() / ПрочитатьJSON() доступны и на клиенте, и на сервере. Обращение к базе и HTTP-запросы к внешним сервисам держите на сервере: так не гоняются лишние данные между клиентом и сервером, а в веб-клиенте не мешают ограничения браузера.