fix(bitra-patch): 4 runtime bugs in BSL — works alias, Projects.Клиент, UUID composite-types, safe JSON serialization

This commit is contained in:
Roman Chesnokov
2026-05-15 17:45:38 +05:00
parent 529464a175
commit 252c5e38a7
2 changed files with 75 additions and 18 deletions
@@ -25,7 +25,11 @@
// Дефолтные параметры записи JSON (без переносов строк недоступно в 8.3.14 — используем умолчание).
ПараметрыJSON = Новый ПараметрыЗаписиJSON;
ЗаписьJSON.УстановитьСтроку(ПараметрыJSON);
ЗаписатьJSON(ЗаписьJSON, Данные);
// ЗаписатьJSON не умеет сериализовать произвольные 1С-типы (ссылки, перечисления, ХранилищеЗначения и т.п.).
// Перед записью нормализуем структуру/массив — превращаем «не примитивы» в строку.
БезопасныеДанные = НормализоватьДляJSON(Данные);
ЗаписатьJSON(ЗаписьJSON, БезопасныеДанные);
Ответ = Новый HTTPСервисОтвет(Код);
Ответ.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
@@ -34,6 +38,50 @@
КонецФункции
// Рекурсивно нормализует значение для безопасной сериализации в JSON.
// Структура → новая Структура с нормализованными значениями.
// Массив → новый Массив с нормализованными элементами.
// Дата/Число/Булево/Строка/Неопределено/Null → как есть.
// Остальное (ссылки, перечисления, любые объекты 1С) → Строка(Значение).
//
Функция НормализоватьДляJSON(Знач Значение) Экспорт
Если Значение = Неопределено ИЛИ Значение = Null Тогда
Возврат Значение;
КонецЕсли;
Тип = ТипЗнч(Значение);
Если Тип = Тип("Структура") Тогда
Результат = Новый Структура;
Для Каждого КлючЗначение Из Значение Цикл
Результат.Вставить(КлючЗначение.Ключ, НормализоватьДляJSON(КлючЗначение.Значение));
КонецЦикла;
Возврат Результат;
ИначеЕсли Тип = Тип("Соответствие") Тогда
Результат = Новый Соответствие;
Для Каждого КлючЗначение Из Значение Цикл
Результат.Вставить(КлючЗначение.Ключ, НормализоватьДляJSON(КлючЗначение.Значение));
КонецЦикла;
Возврат Результат;
ИначеЕсли Тип = Тип("Массив") Тогда
Результат = Новый Массив;
Для Каждого Элемент Из Значение Цикл
Результат.Добавить(НормализоватьДляJSON(Элемент));
КонецЦикла;
Возврат Результат;
ИначеЕсли Тип = Тип("Строка") ИЛИ Тип = Тип("Число") ИЛИ Тип = Тип("Булево") ИЛИ Тип = Тип("Дата") Тогда
Возврат Значение;
Иначе
// Ссылки, перечисления, ХранилищеЗначения, прочие объекты 1С → строкой
Попытка
Возврат Строка(Значение);
Исключение
Возврат "";
КонецПопытки;
КонецЕсли;
КонецФункции
// Сериализованная ошибка.
//
Функция СформироватьОтветОшибки(Знач СообщениеОшибки, Знач Код = 500) Экспорт
@@ -62,13 +110,22 @@
КонецФункции
// Строковое представление GUID ссылки или пустая строка.
// Безопасно для составных типов (где значение может быть строкой):
// - если значение пусто → "";
// - если ссылка → её UUID строкой;
// - если строка/число/булево/etc → Строка(Значение).
//
Функция UUID(Знач Ссылка) Экспорт
Если НЕ ЗначениеЗаполнено(Ссылка) Тогда
Возврат "";
КонецЕсли;
Возврат Строка(Ссылка.УникальныйИдентификатор());
Попытка
Возврат Строка(Ссылка.УникальныйИдентификатор());
Исключение
// Не ссылка (составной тип измерения / Число / Строка / Перечисление и т.п.)
Возврат Строка(Ссылка);
КонецПопытки;
КонецФункции
@@ -83,23 +83,23 @@
Запрос1С.Текст =
"ВЫБРАТЬ ПЕРВЫЕ " + Формат(Лимит, "ЧГ=") + "
| Работы.Ссылка КАК Ссылка,
| Работы.Номер КАК Номер,
| Работы.Дата КАК Дата,
| Работы.Исполнитель КАК Исполнитель,
| Работы.Автор КАК Автор,
| Работы.Подразделение КАК Подразделение,
| Работы.Офис КАК Офис,
| Работы.Утвержден КАК Утвержден,
| Работы.Комментарий КАК Комментарий,
| Работы.ИтогоЧасов КАК ИтогоЧасов
| ДокРаботы.Ссылка КАК Ссылка,
| ДокРаботы.Номер КАК Номер,
| ДокРаботы.Дата КАК Дата,
| ДокРаботы.Исполнитель КАК Исполнитель,
| ДокРаботы.Автор КАК Автор,
| ДокРаботы.Подразделение КАК Подразделение,
| ДокРаботы.Офис КАК Офис,
| ДокРаботы.Утвержден КАК Утвержден,
| ДокРаботы.Комментарий КАК Комментарий,
| ДокРаботы.ИтогоЧасов КАК ИтогоЧасов
|ИЗ
| Документ.Работы КАК Работы
| Документ.Работы КАК ДокРаботы
|ГДЕ
| Работы.Дата >= &МодифицированоПосле
| И Работы.Проведен
| ДокРаботы.Дата >= &МодифицированоПосле
| И ДокРаботы.Проведен
|УПОРЯДОЧИТЬ ПО
| Работы.Дата УБЫВ";
| ДокРаботы.Дата УБЫВ";
Выборка = Запрос1С.Выполнить().Выбрать();
Результат = Новый Массив;
@@ -140,8 +140,8 @@
| Проекты.Наименование КАК Наименование,
| Проекты.EVA_ID КАК EvaID,
| Проекты.Кодификатор КАК Кодификатор,
| Проекты.Владелец КАК Клиент,
| Проекты.Владелец.Наименование КАК КлиентИмя,
| Проекты.Клиент КАК Клиент,
| Проекты.Клиент.Наименование КАК КлиентИмя,
| Проекты.Договор КАК Договор,
| Проекты.Конфигурация КАК Конфигурация,
| Проекты.Офис КАК Офис,