Создаваемая структура заполняется свойствами из исходной фиксированной структуры.
Синтаксис
Новый Структура(<ФиксированнаяСтруктура>)Полное описание, параметры и ограничения
Структура.На основании фиксированной структуры
Структура (Structure)
На основании фиксированной структуры
Доступен, начиная с версии 8.3.2.
Синтаксис:
Новый Структура(<ФиксированнаяСтруктура>)
Параметры:
<ФиксированнаяСтруктура> (необязательный)
Тип: ФиксированнаяСтруктура.
Фиксированная структура.
Описание:
Создаваемая структура заполняется свойствами из исходной фиксированной структуры.
Использование в версии:
Доступен, начиная с версии 8.3.2.
Методическая информация
Практические примеры
Неизменяемый пакет товара и три профиля JSON: шесть вариантов конструкторов без неизвестных объектов
Из собственных значений A01/Книга/3/250 делаем неизменяемые снимки двумя способами. Получаем редактируемую копию, создаём версию5/270 с пустым объектом extra, затем записываем и читаем JSON со стандартными, читаемыми и компактными параметрами. Проверяем все поля, типы, независимость скалярных данных, оформление и экранирование.
Где и как запускать
Полный серверный общий модуль УчебныйПакет своей пустой конфигурации УчебныйСнимокJSON85 и отдельный модуль формы. В1С не запускался.
Подготовка
НОВАЯ пустая отдельная учебная база точно8.5.1.1343, имя конфигурации УчебныйСнимокJSON85, совместимость Не использовать. Нет бизнес-объектов, расширений, подписок и фоновых заданий; модули вручную пустые, кроме своего общего модуля. Рабочие конфигурации и записи не используются.
Общий модуль УчебныйПакет: Сервер=Да, Вызов сервера=Да, Клиент=Нет, Глобальный=Нет, Привилегированный=Нет. Вставьте весь основной модуль. Своя внешняя обработка УчебныйСнимокJSON85 → управляемая Форма: команда/кнопка Выполнить с действием Выполнить; реквизиты не нужны. Полный отдельный модуль формы приведён ниже.
Будущая ручная подготовка: сохранить конфигурацию, Конфигурация → Обновить конфигурацию базы данных (F7), открыть новый собственный клиент и свою обработку. Здесь F7, код, сериализация и форма не выполнялись.
Все значения создаёт сам код. Четыре обязательных ключа 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 → управляемая Форма → Модуль
Полный отдельный модуль формы с вызовом своего серверного общего модуля; не выполнялся.
&НаКлиенте
Процедура Выполнить(Команда)
ВыполнитьНаСервере();
Сообщить("Снимки, редактируемая копия и три обратных преобразования собственного пакета проверены");
КонецПроцедуры
&НаСервереБезКонтекста
Процедура ВыполнитьНаСервере()
УчебныйПакет.ВыполнитьПример();
КонецПроцедурыРазбор по шагам
Новый ФиксированнаяСтруктура(РабочийИсходник) копирует четыре подготовленных поля. Второй вариант строит тот же скалярный снимок прямо по строке имён и значениям. Полная проверка использует четыре известные ключа, а не неопределённый порядок обхода фиксированной структуры.
Новый ФиксированнаяСтруктура без параметров создаёт пустой объект дополнительных свойств. Его тип и количество0 проверены. Пустой объект полезен для явного extra:{}, когда контракт учебного сообщения требует само поле, но необязательные сведения отсутствуют.
Новый Структура(Снимок) возвращает редактируемый контейнер. Меняем stock/price на5/270, добавляем extra и снова фиксируем окончательный пакет. Затем изменяем рабочий контейнер на9/990 и очищаем исходный: старые снимки остаются3/250, отправляемый учебный пакет5/270.
ПараметрыЗаписиJSON без аргументов применяются в первом реальном преобразовании. В справке есть противоречие отступа по умолчанию: свойство СимволыОтступа говорит о пустой строке, аргумент конструктора — об одном пробеле. Код фиксирует фактическое значение, допускает только эти два описанных варианта и не заявляет, какой подтвердился в1С.
Именованный конструктор параметров используется для двух явных профилей: Unix с двумя пробелами и Нет с пустым отступом. Все девять свойств readonly: не присваиваем их после создания. Двойные кавычки включены; специальные символы экранируются явными пятью флагами.
Писатель и читатель работают только со строками памяти. ЗаписатьJSON прямо поддерживает ФиксированнаяСтруктура; ПрочитатьJSON(...,Ложь) возвращает обычную Структура. Все пять ключей, четыре полных значения/типа и пустой extra сверяются после каждого из трёх преобразований.
Отдельно проверяем LF без CR для Unix, отсутствие LF/CR для компактного профиля и отсутствие сырых заданных специальных символов при явном экранировании. Для стандартного профиля не требуем ту же побайтовую раскладку. Порядок JSON-свойств не принимается за контракт.
Восстановленному сообщению задаём stock=7: исходный фиксированный пакет остаётся5/270. Итоговое произведение5×270=1350 — арифметика учебных чисел, не реальная цена, сумма сделки или отправка сообщения.
Как проверить результат
Будущий результат: три восстановленных объекта имеют исходные sku/title, stock5, price270 и пустой объект extra. После локального изменения восстановленной копии на7 пакет по-прежнему содержит5. Старые снимки сохраняют3/250, исходный контейнер очищен.
Будущий отрицательный контроль: в ПрочитатьСвойПакетИзСтроки сразу перед ПроверитьСвоиПоляПакета(Пакет,5,270,Истина) вставьте Пакет.stock = "5";. При тех же пяти ключах проверка должна отклонить строковый stock по типу. Не меняйте эталон и общий проверяющий код; после опыта верните весь исходный модуль и откройте новый свой сеанс.
Сверяйте восстановленные поля, не равенство трёх текстов JSON. У default-профиля показана фактическая длина отступа0 или1; это диагностическая граница противоречивой справки, а не подтверждённое в1С значение по умолчанию.
runtimeVerifiedScenarios=0. Здесь не запускались BSL, JSON-писатель/читатель или форма, не выполнялись HTTP-запросы, запись файлов, изменение параметров сеанса или базы. Исходный формат специально учебный: это не заявленный контракт Avito или другого внешнего API.
Ожидаемый результат
Шесть конструкторов решают одну задачу подготовки и проверки собственной версии сообщения: источник, снимки, редактируемая копия, пустой объект дополнений и три различающихся представления JSON.
На что обратить внимание
ФиксированнаяСтруктура не даёт универсального глубокого клонирования произвольного графа. Здесь значения скалярные, а вложенный extra сам фиксирован и пуст. Не заменяйте его неизвестной изменяемой структурой и не обещайте полную независимость чужих вложенных объектов.
Порядок обхода ФиксированнаяСтруктура неопределён. Проверка названа по известным ключам и полным значениям, не по номерам пар. Ключи должны удовлетворять именованию переменных BSL; произвольные ключи внешнего JSON могут потребовать Соответствие.
Свойства ПараметрыЗаписиJSON readonly. Все необходимые значения задаются конструктором; ПереносСтрокJSON и ЭкранированиеСимволовJSON — enum, не строки. Авто зависит от ОС, поэтому только явному Unix задаётся проверка LF без CR.
Отступ по умолчанию в установленной справке описан противоречиво. Не подменяйте наблюдаемый стандартный отступ единственным догаданным эталоном; явные профили имеют однозначно заданные два пробела и пустую строку.
ПрочитатьJSON не сохраняет фиксированность структуры. После чтения получаем редактируемую структуру и проверяем типы значений. Строка "5" не равна числу5 для нашего контракта, даже если внешне они похожи.
Корректное экранирование и обратное чтение не являются универсальной защитой XSS. Не вставляйте default-JSON в HTML/JavaScript произвольным способом. Этот урок показывает конкретное представление данных, не проверенный сценарий веб-встраивания или интеграции.
Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.