ПараметрыЗаписиJSON.По умолчанию

Конструкторы

Синтаксис и применение ПараметрыЗаписиJSON.По умолчанию в платформе 1С:Предприятие. Описание и примеры кода.

Синтаксис

Новый ПараметрыЗаписиJSON()
Полное описание, параметры и ограничения

ПараметрыЗаписиJSON.По умолчанию

ПараметрыЗаписиJSON (JSONWriterSettings)

По умолчанию

Доступен, начиная с версии 8.3.6.

Синтаксис:
Новый ПараметрыЗаписиJSON()
Использование в версии:

Доступен, начиная с версии 8.3.6.

Методическая информация

Практические примеры

Неизменяемый пакет товара и три профиля JSON: шесть вариантов конструкторов без неизвестных объектов

Из собственных значений A01/Книга/3/250 делаем неизменяемые снимки двумя способами. Получаем редактируемую копию, создаём версию5/270 с пустым объектом extra, затем записываем и читаем JSON со стандартными, читаемыми и компактными параметрами. Проверяем все поля, типы, независимость скалярных данных, оформление и экранирование.

Где и как запускать

Полный серверный общий модуль УчебныйПакет своей пустой конфигурации УчебныйСнимокJSON85 и отдельный модуль формы. В1С не запускался.

Подготовка

  1. НОВАЯ пустая отдельная учебная база точно8.5.1.1343, имя конфигурации УчебныйСнимокJSON85, совместимость Не использовать. Нет бизнес-объектов, расширений, подписок и фоновых заданий; модули вручную пустые, кроме своего общего модуля. Рабочие конфигурации и записи не используются.

  2. Общий модуль УчебныйПакет: Сервер=Да, Вызов сервера=Да, Клиент=Нет, Глобальный=Нет, Привилегированный=Нет. Вставьте весь основной модуль. Своя внешняя обработка УчебныйСнимокJSON85 → управляемая Форма: команда/кнопка Выполнить с действием Выполнить; реквизиты не нужны. Полный отдельный модуль формы приведён ниже.

  3. Будущая ручная подготовка: сохранить конфигурацию, Конфигурация → Обновить конфигурацию базы данных (F7), открыть новый собственный клиент и свою обработку. Здесь F7, код, сериализация и форма не выполнялись.

  4. Все значения создаёт сам код. Четыре обязательных ключа sku/title/stock/price допустимы как имена переменных BSL. title содержит кириллицу, <>, &, одинарные кавычки, слеш и U+2028/U+2029. extra — действительно пустая ФиксированнаяСтруктура, не Неопределено и не строка с текстом {}.

Процедура ВыполнитьПример() Экспорт
    ПроверитьСвойПустойСтенд();
    РабочийИсходник = Новый Структура("sku,title,stock,price", "A01", СвоеНазваниеПакета(), 3, 250);
    Снимок = Новый ФиксированнаяСтруктура(РабочийИсходник);
    Именованный = Новый ФиксированнаяСтруктура("sku,title,stock,price", "A01", СвоеНазваниеПакета(), 3, 250);
    Если ТипЗнч(Снимок) <> Тип("ФиксированнаяСтруктура") Или ТипЗнч(Именованный) <> Тип("ФиксированнаяСтруктура") Тогда
        ВызватьИсключение "Оба способа создания дают фиксированные снимки";
    КонецЕсли;
    ПустыеДополнения = Новый ФиксированнаяСтруктура;
    Если ТипЗнч(ПустыеДополнения) <> Тип("ФиксированнаяСтруктура") Или ПустыеДополнения.Количество() <> 0 Тогда
        ВызватьИсключение "Нужен собственный пустой неизменяемый объект дополнений";
    КонецЕсли;
    ПроверитьСвоиПоляПакета(Снимок, 3, 250, Ложь);
    ПроверитьСвоиПоляПакета(Именованный, 3, 250, Ложь);
    РабочийИсходник.stock = 8;
    РабочийИсходник.price = 999;
    ПроверитьСвоиПоляПакета(РабочийИсходник, 8, 999, Ложь);
    ПроверитьСвоиПоляПакета(Снимок, 3, 250, Ложь);
    Рабочий = Новый Структура(Снимок);
    Если ТипЗнч(Рабочий) <> Тип("Структура") Тогда
        ВызватьИсключение "Рабочая копия должна быть изменяемой структурой";
    КонецЕсли;
    Рабочий.stock = 5;
    Рабочий.price = 270;
    Рабочий.Вставить("extra", ПустыеДополнения);
    Пакет = Новый ФиксированнаяСтруктура(Рабочий);
    Если ТипЗнч(Пакет) <> Тип("ФиксированнаяСтруктура") Тогда
        ВызватьИсключение "Окончательный собственный пакет фиксирован";
    КонецЕсли;
    ПроверитьСвоиПоляПакета(Пакет, 5, 270, Истина);
    Рабочий.stock = 9;
    Рабочий.price = 990;
    РабочийИсходник.Очистить();
    Если РабочийИсходник.Количество() <> 0 Тогда
        ВызватьИсключение "Собственный исходный рабочий контейнер очищен";
    КонецЕсли;
    ПроверитьСвоиПоляПакета(Рабочий, 9, 990, Истина);
    ПроверитьСвоиПоляПакета(Снимок, 3, 250, Ложь);
    ПроверитьСвоиПоляПакета(Именованный, 3, 250, Ложь);
    ПроверитьСвоиПоляПакета(Пакет, 5, 270, Истина);
    Стандартные = Новый ПараметрыЗаписиJSON;
    СтандартныйОтступ = Стандартные.СимволыОтступа;
    Если СтандартныйОтступ <> "" И СтандартныйОтступ <> " " Тогда
        ВызватьИсключение "Отступ по умолчанию не совпал ни с одним из двух описаний установленной справки";
    КонецЕсли;
    ПроверитьСвоиПараметрыПакета(Стандартные, ПереносСтрокJSON.Авто, СтандартныйОтступ, Ложь);
    Читаемые = Новый ПараметрыЗаписиJSON(ПереносСтрокJSON.Unix, "  ", Истина,
        ЭкранированиеСимволовJSON.Нет, Истина, Истина, Истина, Истина, Истина);
    Компактные = Новый ПараметрыЗаписиJSON(ПереносСтрокJSON.Нет, "", Истина,
        ЭкранированиеСимволовJSON.Нет, Истина, Истина, Истина, Истина, Истина);
    Профили = Новый Массив;
    Профили.Добавить(Новый Структура("Имя,Параметры,Перенос,Отступ,Экранировать",
        "По умолчанию", Стандартные, ПереносСтрокJSON.Авто, СтандартныйОтступ, Ложь));
    Профили.Добавить(Новый Структура("Имя,Параметры,Перенос,Отступ,Экранировать",
        "Читаемый Unix", Читаемые, ПереносСтрокJSON.Unix, "  ", Истина));
    Профили.Добавить(Новый Структура("Имя,Параметры,Перенос,Отступ,Экранировать",
        "Компактный", Компактные, ПереносСтрокJSON.Нет, "", Истина));
    Для Каждого Профиль Из Профили Цикл
        Текст = ЗаписатьСвойПакетВСтроку(Пакет, Профиль.Параметры, Профиль.Перенос, Профиль.Отступ, Профиль.Экранировать);
        Восстановленный = ПрочитатьСвойПакетИзСтроки(Текст);
        ПроверитьСвоеПредставлениеПакета(Текст, Профиль.Перенос, Профиль.Экранировать);
        ПроверитьСвоиПоляПакета(Пакет, 5, 270, Истина);
        Восстановленный.stock = 7;
        ПроверитьСвоиПоляПакета(Восстановленный, 7, 270, Истина);
        ПроверитьСвоиПоляПакета(Пакет, 5, 270, Истина);
        Сообщить(Профиль.Имя);
        Сообщить(Текст);
    КонецЦикла;
    Сообщить(СтрШаблон("Пакет сохранён: stock=%1, price=%2, произведение=%3; длина стандартного отступа=%4",
        Пакет.stock, Пакет.price, Пакет.stock * Пакет.price, СтрДлина(СтандартныйОтступ)));
КонецПроцедуры

Процедура ПроверитьСвойПустойСтенд()
    Если Метаданные.Справочники.Количество() <> 0 Или Метаданные.Документы.Количество() <> 0 Или Метаданные.Перечисления.Количество() <> 0 Или Метаданные.РегистрыСведений.Количество() <> 0 Или Метаданные.РегистрыНакопления.Количество() <> 0 Или Метаданные.РегистрыБухгалтерии.Количество() <> 0 Или Метаданные.РегистрыРасчета.Количество() <> 0 Или Метаданные.ПланыВидовХарактеристик.Количество() <> 0 Или Метаданные.ПланыВидовРасчета.Количество() <> 0 Или Метаданные.ПланыСчетов.Количество() <> 0 Или Метаданные.ПланыОбмена.Количество() <> 0 Или Метаданные.Последовательности.Количество() <> 0 Или Метаданные.БизнесПроцессы.Количество() <> 0 Или Метаданные.Задачи.Количество() <> 0 Или Метаданные.ОбщиеРеквизиты.Количество() <> 0 Или Метаданные.ПодпискиНаСобытия.Количество() <> 0 Или Метаданные.РегламентныеЗадания.Количество() <> 0 Или Метаданные.ВнешниеИсточникиДанных.Количество() <> 0 Тогда
        ВызватьИсключение "Нужен только свой новый пустой учебный стенд";
    КонецЕсли;
    Если Метаданные.ЕстьИзмененияРасширениямиКонфигурации() Тогда
        ВызватьИсключение "Свой сеанс не должен изменяться расширениями";
    КонецЕсли;
    Источники = Новый Массив;
    Источники.Добавить(ИсточникРасширенийКонфигурации.БазаДанных);
    Источники.Добавить(ИсточникРасширенийКонфигурации.СеансАктивные);
    Источники.Добавить(ИсточникРасширенийКонфигурации.СеансОтключенные);
    Для Каждого Источник Из Источники Цикл
        Расширения = РасширенияКонфигурации.Получить(, Источник);
        Если ТипЗнч(Расширения) <> Тип("Массив") Тогда
            ВызватьИсключение "Native список расширений должен иметь тип Массив";
        КонецЕсли;
        Если Расширения.Количество() <> 0 Тогда
            ВызватьИсключение "В своём новом стенде нет расширений базы или сеанса";
        КонецЕсли;
    КонецЦикла;
    Если ТранзакцияАктивна() Тогда
        ВызватьИсключение "Чужая или вложенная активная транзакция не допускается";
    КонецЕсли;
КонецПроцедуры

Функция СвоеНазваниеПакета()
    Возврат "Книга <учебная>& 'тест'/" + Символ(8232) + Символ(8233);
КонецФункции

Процедура ПроверитьСвоиПоляПакета(Объект, Запас, Цена, СДополнениями)
    Если ТипЗнч(Объект) <> Тип("Структура") И ТипЗнч(Объект) <> Тип("ФиксированнаяСтруктура") Тогда
        ВызватьИсключение "Нужен только собственный подготовленный пакет";
    КонецЕсли;
    Ожидание = Новый Структура("sku,title,stock,price", "A01", СвоеНазваниеПакета(), Запас, Цена);
    Если Объект.Количество() <> ?(СДополнениями, 5, 4) Тогда
        ВызватьИсключение "Не совпал полный набор собственных полей пакета";
    КонецЕсли;
    Для Каждого Имя Из СтрРазделить("sku,title,stock,price", ",") Цикл
        Если Не Объект.Свойство(Имя, Факт) Тогда
            ВызватьИсключение "Отсутствует собственное обязательное поле " + Имя;
        КонецЕсли;
        Ожидание.Свойство(Имя, Эталон);
        Если ТипЗнч(Факт) <> ТипЗнч(Эталон) Или Факт <> Эталон Тогда
            ВызватьИсключение "Не совпали тип и полное собственное значение поля " + Имя;
        КонецЕсли;
    КонецЦикла;
    Если СДополнениями Тогда
        Если Не Объект.Свойство("extra", Дополнения) Тогда
            ВызватьИсключение "Пустой объект дополнений не должен исчезнуть";
        КонецЕсли;
        Если ТипЗнч(Дополнения) <> Тип("Структура") И ТипЗнч(Дополнения) <> Тип("ФиксированнаяСтруктура") Тогда
            ВызватьИсключение "Дополнения должны быть объектом, не строкой, массивом или null";
        КонецЕсли;
        Если Дополнения.Количество() <> 0 Тогда
            ВызватьИсключение "Собственный extra должен быть именно пустым объектом";
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

Процедура ПроверитьСвоиПараметрыПакета(Параметры, Перенос, Отступ, Экранировать)
    Если ТипЗнч(Параметры) <> Тип("ПараметрыЗаписиJSON") Тогда
        ВызватьИсключение "Нужны собственные параметры записи JSON";
    КонецЕсли;
    Если Параметры.ПереносСтрок <> Перенос Или Параметры.СимволыОтступа <> Отступ
        Или ТипЗнч(Параметры.СимволыОтступа) <> Тип("Строка")
        Или Не Параметры.ИспользоватьДвойныеКавычки
        Или Параметры.ЭкранированиеСимволов <> ЭкранированиеСимволовJSON.Нет
        Или Параметры.ЭкранироватьУгловыеСкобки <> Экранировать
        Или Не Параметры.ЭкранироватьРазделителиСтрок
        Или Параметры.ЭкранироватьАмперсанд <> Экранировать
        Или Параметры.ЭкранироватьОдинарныеКавычки <> Экранировать
        Или Параметры.ЭкранироватьСлеш <> Экранировать Тогда
        ВызватьИсключение "Не совпали все девять параметров собственного профиля JSON";
    КонецЕсли;
КонецПроцедуры

Функция ЗаписатьСвойПакетВСтроку(Пакет, Параметры, Перенос, Отступ, Экранировать)
    ПроверитьСвоиПоляПакета(Пакет, 5, 270, Истина);
    ПроверитьСвоиПараметрыПакета(Параметры, Перенос, Отступ, Экранировать);
    Запись = Новый ЗаписьJSON;
    Запись.УстановитьСтроку(Параметры);
    Попытка
        ПроверитьСвоиПараметрыПакета(Запись.Параметры, Перенос, Отступ, Экранировать);
        ЗаписатьJSON(Запись, Пакет);
        Возврат Запись.Закрыть();
    Исключение
        Запись.Закрыть();
        ВызватьИсключение;
    КонецПопытки;
КонецФункции

Функция ПрочитатьСвойПакетИзСтроки(Текст)
    Чтение = Новый ЧтениеJSON;
    Чтение.УстановитьСтроку(Текст);
    Попытка
        Пакет = ПрочитатьJSON(Чтение, Ложь);
    Исключение
        Чтение.Закрыть();
        ВызватьИсключение;
    КонецПопытки;
    Чтение.Закрыть();
    Если ТипЗнч(Пакет) <> Тип("Структура") Тогда
        ВызватьИсключение "Верхний JSON-объект восстановлен как обычная Структура";
    КонецЕсли;
    ПроверитьСвоиПоляПакета(Пакет, 5, 270, Истина);
    Возврат Пакет;
КонецФункции

Процедура ПроверитьСвоеПредставлениеПакета(Текст, Режим, Экранировать)
    Если Режим = ПереносСтрокJSON.Unix Тогда
        Если СтрНайти(Текст, Символ(10)) = 0 Или СтрНайти(Текст, Символ(13)) <> 0 Тогда
            ВызватьИсключение "Читаемый профиль должен использовать только перенос Unix";
        КонецЕсли;
    ИначеЕсли Режим = ПереносСтрокJSON.Нет Тогда
        Если СтрНайти(Текст, Символ(10)) <> 0 Или СтрНайти(Текст, Символ(13)) <> 0 Тогда
            ВызватьИсключение "Компактный профиль не содержит переводов строк";
        КонецЕсли;
    КонецЕсли;
    Если Экранировать Тогда
        Если СтрНайти(Текст, "<") <> 0 Или СтрНайти(Текст, ">") <> 0 Или СтрНайти(Текст, "&") <> 0
            Или СтрНайти(Текст, "'") <> 0 Или СтрНайти(Текст, "/") <> 0
            Или СтрНайти(Текст, Символ(8232)) <> 0 Или СтрНайти(Текст, Символ(8233)) <> 0 Тогда
            ВызватьИсключение "Не совпало заданное экранирование собственной строки";
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры
УчебныйСнимокJSON85.Форма

Своя внешняя обработка УчебныйСнимокJSON85 → управляемая Форма → Модуль

Полный отдельный модуль формы с вызовом своего серверного общего модуля; не выполнялся.

&НаКлиенте
Процедура Выполнить(Команда)
    ВыполнитьНаСервере();
    Сообщить("Снимки, редактируемая копия и три обратных преобразования собственного пакета проверены");
КонецПроцедуры

&НаСервереБезКонтекста
Процедура ВыполнитьНаСервере()
    УчебныйПакет.ВыполнитьПример();
КонецПроцедуры

Разбор по шагам

  1. Новый ФиксированнаяСтруктура(РабочийИсходник) копирует четыре подготовленных поля. Второй вариант строит тот же скалярный снимок прямо по строке имён и значениям. Полная проверка использует четыре известные ключа, а не неопределённый порядок обхода фиксированной структуры.

  2. Новый ФиксированнаяСтруктура без параметров создаёт пустой объект дополнительных свойств. Его тип и количество0 проверены. Пустой объект полезен для явного extra:{}, когда контракт учебного сообщения требует само поле, но необязательные сведения отсутствуют.

  3. Новый Структура(Снимок) возвращает редактируемый контейнер. Меняем stock/price на5/270, добавляем extra и снова фиксируем окончательный пакет. Затем изменяем рабочий контейнер на9/990 и очищаем исходный: старые снимки остаются3/250, отправляемый учебный пакет5/270.

  4. ПараметрыЗаписиJSON без аргументов применяются в первом реальном преобразовании. В справке есть противоречие отступа по умолчанию: свойство СимволыОтступа говорит о пустой строке, аргумент конструктора — об одном пробеле. Код фиксирует фактическое значение, допускает только эти два описанных варианта и не заявляет, какой подтвердился в1С.

  5. Именованный конструктор параметров используется для двух явных профилей: Unix с двумя пробелами и Нет с пустым отступом. Все девять свойств readonly: не присваиваем их после создания. Двойные кавычки включены; специальные символы экранируются явными пятью флагами.

  6. Писатель и читатель работают только со строками памяти. ЗаписатьJSON прямо поддерживает ФиксированнаяСтруктура; ПрочитатьJSON(...,Ложь) возвращает обычную Структура. Все пять ключей, четыре полных значения/типа и пустой extra сверяются после каждого из трёх преобразований.

  7. Отдельно проверяем LF без CR для Unix, отсутствие LF/CR для компактного профиля и отсутствие сырых заданных специальных символов при явном экранировании. Для стандартного профиля не требуем ту же побайтовую раскладку. Порядок JSON-свойств не принимается за контракт.

  8. Восстановленному сообщению задаём stock=7: исходный фиксированный пакет остаётся5/270. Итоговое произведение5×270=1350 — арифметика учебных чисел, не реальная цена, сумма сделки или отправка сообщения.

Как проверить результат

  1. Будущий результат: три восстановленных объекта имеют исходные sku/title, stock5, price270 и пустой объект extra. После локального изменения восстановленной копии на7 пакет по-прежнему содержит5. Старые снимки сохраняют3/250, исходный контейнер очищен.

  2. Будущий отрицательный контроль: в ПрочитатьСвойПакетИзСтроки сразу перед ПроверитьСвоиПоляПакета(Пакет,5,270,Истина) вставьте Пакет.stock = "5";. При тех же пяти ключах проверка должна отклонить строковый stock по типу. Не меняйте эталон и общий проверяющий код; после опыта верните весь исходный модуль и откройте новый свой сеанс.

  3. Сверяйте восстановленные поля, не равенство трёх текстов JSON. У default-профиля показана фактическая длина отступа0 или1; это диагностическая граница противоречивой справки, а не подтверждённое в1С значение по умолчанию.

  4. runtimeVerifiedScenarios=0. Здесь не запускались BSL, JSON-писатель/читатель или форма, не выполнялись HTTP-запросы, запись файлов, изменение параметров сеанса или базы. Исходный формат специально учебный: это не заявленный контракт Avito или другого внешнего API.

Ожидаемый результат

Шесть конструкторов решают одну задачу подготовки и проверки собственной версии сообщения: источник, снимки, редактируемая копия, пустой объект дополнений и три различающихся представления JSON.

На что обратить внимание

  1. ФиксированнаяСтруктура не даёт универсального глубокого клонирования произвольного графа. Здесь значения скалярные, а вложенный extra сам фиксирован и пуст. Не заменяйте его неизвестной изменяемой структурой и не обещайте полную независимость чужих вложенных объектов.

  2. Порядок обхода ФиксированнаяСтруктура неопределён. Проверка названа по известным ключам и полным значениям, не по номерам пар. Ключи должны удовлетворять именованию переменных BSL; произвольные ключи внешнего JSON могут потребовать Соответствие.

  3. Свойства ПараметрыЗаписиJSON readonly. Все необходимые значения задаются конструктором; ПереносСтрокJSON и ЭкранированиеСимволовJSON — enum, не строки. Авто зависит от ОС, поэтому только явному Unix задаётся проверка LF без CR.

  4. Отступ по умолчанию в установленной справке описан противоречиво. Не подменяйте наблюдаемый стандартный отступ единственным догаданным эталоном; явные профили имеют однозначно заданные два пробела и пустую строку.

  5. ПрочитатьJSON не сохраняет фиксированность структуры. После чтения получаем редактируемую структуру и проверяем типы значений. Строка "5" не равна числу5 для нашего контракта, даже если внешне они похожи.

  6. Корректное экранирование и обратное чтение не являются универсальной защитой XSS. Не вставляйте default-JSON в HTML/JavaScript произвольным способом. Этот урок показывает конкретное представление данных, не проверенный сценарий веб-встраивания или интеграции.

Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.

Не хотите разбираться сами?

Адаптируем это решение под вашу базу. Оценка бесплатно.

Оставить задачу

1С, 1С:Предприятие — товарные знаки ООО «1С». Сайт не является официальным представительством фирмы «1С» и не аффилирован с ней.