A1sCode библиотека 1С

Зачем это нужно

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 минут)

  1. Сделайте StructCompact и очистите структуру от «пустых» полей.
  2. Реализуйте StructPick/StructOmit и соберите «тонкую» шапку документа.
  3. Сделайте StructRemapKeys и примените карту переименования под внешний контракт.
  4. Соберите конвейер: ToStruct → Flatten → Compact → Remap → Defaults.
  5. Попробуйте StructDeepMerge на двух вложенных структурах настроек.

Чек-лист

Что дальше

День 18: A1sS — Значение в строку (AsString) — безопасные преобразования и текстовая нормализация.