Зачем это нужно
- Очистка: убрать пустые поля перед сериализацией/логированием.
- Отбор: оставить только нужные ключи или исключить лишние.
- Переименование: привести ключи к внешнему контракту.
- Слияние: применить дефолты, объединить несколько источников.
- Уплощение: сделать «плоские» ключи
a.b.cдля экспорта.
Compact — убрать «пустые» значения
Ориентируемся на семантику Дня 10: Empty/NotEmpty (0 и Ложь — НЕ
пусто).
Функция StructCompact(СтрВход) Экспорт
Рез = Новый Структура;
Для каждого П Из СтрВход Цикл
Если A1sO.NotEmpty(П.Значение) Тогда
Рез.Вставить(П.Ключ, П.Значение);
КонецЕсли;
КонецЦикла;
Возврат Рез;
КонецФункции
Pick / Omit — выбрать или исключить ключи
Функция StructPick(СтрВход, Поля) Экспорт // Поля — Массив строк
Рез = Новый Структура;
Если A1sO.Empty(Поля) Тогда Возврат Рез; КонецЕсли;
Для каждого Имя Из Поля Цикл
Если СтрВход.Свойство(Имя) Тогда
Рез.Вставить(Имя, СтрВход.Получить(Имя));
КонецЕсли;
КонецЦикла;
Возврат Рез;
КонецФункции
Функция StructOmit(СтрВход, Исключить) Экспорт // Исключить — Массив строк
Рез = Новый Структура;
Для каждого П Из СтрВход Цикл
Если Исключить.Найти(П.Ключ) = Неопределено Тогда
Рез.Вставить(П.Ключ, П.Значение);
КонецЕсли;
КонецЦикла;
Возврат Рез;
КонецФункции
// Использование:
Поля = СтрРазделить("Ссылка,Дата,Номер,Контрагент", ",");
Шапка = A1sO.ToStruct(Док, Поля);
ТолькоИдентификация = StructPick(Шапка, СтрРазделить("Ссылка,Номер,Дата", ","));
БезКомментария = StructOmit(Шапка, СтрРазделить("Комментарий", ","));
Remap — переименование ключей по карте
Функция StructRemapKeys(СтрВход, Карта) Экспорт
// Карта: Соответствие "ВнутреннееИмя" → "ВнешнийКлюч"
Рез = Новый Структура;
Для каждого П Из СтрВход Цикл
Внешн = ?(Карта.СодержитКлюч(П.Ключ), Карта[П.Ключ], П.Ключ);
Рез.Вставить(Внешн, П.Значение);
КонецЦикла;
Возврат Рез;
КонецФункции
Комбинируйте с StructCompact, чтобы не тянуть пустые поля в контракт.
Defaults и Merge — дефолты и объединение
Функция StructDefaults(СтрВход, Дефолты) Экспорт
// Проставить значения по умолчанию, если ключ отсутствует
Рез = Новый Структура;
// Сначала базу копируем
Для каждого П Из СтрВход Цикл
Рез.Вставить(П.Ключ, П.Значение);
КонецЦикла;
// Потом дополняем отсутствующие
Для каждого D Из Дефолты Цикл
Если НЕ Рез.Свойство(D.Ключ) Тогда
Рез.Вставить(D.Ключ, D.Значение);
КонецЕсли;
КонецЦикла;
Возврат Рез;
КонецФункции
Функция StructMerge(Осн, Обн) Экспорт
// Плоское слияние: Обн перезаписывает Осн
Рез = Новый Структура;
Для каждого П Из Осн Цикл
Рез.Вставить(П.Ключ, П.Значение);
КонецЦикла;
Для каждого П Из Обн Цикл
Рез.Вставить(П.Ключ, П.Значение);
КонецЦикла;
Возврат Рез;
КонецФункции
Глубокое слияние (структуры внутри структур)
Функция StructDeepMerge(Л, П) Экспорт
// Л — левый (база), П — правый (обновление), правый важнее
Рез = Новый Структура;
// Сначала скопировать левый
Для каждого A Из Л Цикл
Рез.Вставить(A.Ключ, A.Значение);
КонецЦикла;
// Применить правый
Для каждого B Из П Цикл
Если ТипЗнч(B.Значение) = Тип("Структура")
И Рез.Свойство(B.Ключ)
И ТипЗнч(Рез.Получить(B.Ключ)) = Тип("Структура") Тогда
Рез.Вставить(B.Ключ, StructDeepMerge(Рез.Получить(B.Ключ), B.Значение));
Иначе
Рез.Вставить(B.Ключ, B.Значение);
КонецЕсли;
КонецЦикла;
Возврат Рез;
КонецФункции
Flatten / Unflatten — уплощение и разворачивание
Удобно для экспорта: ключи вида Шапка.Номер, Контрагент.Имя.
Разделитель — точка.
Процедура _StructFlattenRec(СтрВход, Префикс, Рез, Разделитель) Экспорт
Для каждого П Из СтрВход Цикл
Поле = ?(Префикс = "", П.Ключ, Префикс + Разделитель + П.Ключ);
Если ТипЗнч(П.Значение) = Тип("Структура") Тогда
_StructFlattenRec(П.Значение, Поле, Рез, Разделитель);
Иначе
Рез.Вставить(Поле, П.Значение);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Функция StructFlatten(СтрВход, Разделитель = ".") Экспорт
Рез = Новый Структура;
_StructFlattenRec(СтрВход, "", Рез, Разделитель);
Возврат Рез;
КонецФункции
Функция StructUnflatten(Плоская, Разделитель = ".") Экспорт
Рез = Новый Структура;
Для каждого П Из Плоская Цикл
Части = СтрРазделить(П.Ключ, Разделитель);
Послед = Части.ВГраница(); // последний индекс
// Идем внутрь, создавая структуры по пути
Узел = Рез;
Для И = 0 По Послед-1 Цикл
Имя = Части[И];
Лок = ?(Узел.Свойство(Имя), Узел.Получить(Имя), Неопределено);
Если ТипЗнч(Лок) <> Тип("Структура") Тогда
Лок = Новый Структура;
Узел.Вставить(Имя, Лок);
КонецЕсли;
Узел = Узел.Получить(Имя);
КонецЦикла;
Узел.Вставить(Части[Послед], П.Значение);
КонецЦикла;
Возврат Рез;
КонецФункции
Примечание: при совпадении имён-ключей и нехватке типов «внутри» мы создаём структуры на лету.
MapValues — массовое преобразование значений
Удобно нормализовать типы перед экспортом (строки, числа, даты).
Функция StructMapValues(СтрВход, Преобразователь) Экспорт
// Преобразователь(ИмяКлюча, Значение) → НовоеЗначение
Рез = Новый Структура;
Для каждого П Из СтрВход Цикл
Рез.Вставить(П.Ключ, Преобразователь(П.Ключ, П.Значение));
КонецЦикла;
Возврат Рез;
КонецФункции
// Пример нормализации:
Функция _Normalizer(Ключ, Знач) Экспорт
Если ТипЗнч(Знач) = Тип("Дата") Тогда
Возврат A1sO.DateOrEmpty(Знач);
ИначеЕсли ТипЗнч(Знач) = Тип("Число") Тогда
Возврат A1sO.RoundNum(A1sO.NumOrZero(Знач), 2);
ИначеЕсли ТипЗнч(Знач) = Тип("Строка") Тогда
Возврат A1sS.AsString(Знач);
КонецЕсли;
Возврат Знач;
КонецФункции
Пример конвейера: Шапка документа → экспорт
Поля = СтрРазделить("Ссылка,Дата,Номер,Контрагент,Комментарий", ",");
Шапка = A1sO.ToStruct(Док, Поля);
// 1) Расширим «глубоким» полем
Шапка.Вставить("Контрагент.Имя", A1sS.AsString(Док.Контрагент.Наименование));
// 2) Уплощаем и фильтруем пустые
Плоская = StructCompact(StructFlatten(Шапка));
// 3) Переименовываем ключи под API
Карта = Новый Соответствие;
Карта.Вставить("Ссылка", "id");
Карта.Вставить("Дата", "date");
Карта.Вставить("Номер", "number");
Карта.Вставить("Контрагент.Имя", "partnerName");
Карта.Вставить("Комментарий", "comment");
КЭкспорту = StructRemapKeys(Плоская, Карта);
// 4) Дефолты
Деф = Новый Структура("comment", "");
КЭкспорту = StructDefaults(КЭкспорту, Деф);
// Готово для JSON (День 22: A1sJ)
Практика (15–30 минут)
- Сделайте
StructCompactи очистите структуру от «пустых» полей. - Реализуйте
StructPick/StructOmitи соберите «тонкую» шапку документа. - Сделайте
StructRemapKeysи примените карту переименования под внешний контракт. - Соберите конвейер: ToStruct → Flatten → Compact → Remap → Defaults.
- Попробуйте
StructDeepMergeна двух вложенных структурах настроек.
Чек-лист
- □ Я умею очищать структуру от «пустых» значений (
StructCompact). - □ Я выбираю/исключаю ключи (
Pick/Omit), не таская лишнее. - □ Я переименовываю ключи под контракт (
RemapKeys). - □ Я добавляю дефолты и сливаю данные (
Defaults/Merge/DeepMerge). - □ Я уплощаю и разворачиваю структуры (
Flatten/Unflatten) при необходимости.
Что дальше
День 18: A1sS — Значение в строку (AsString) — безопасные преобразования и текстовая нормализация.