Какие преимущества
-
Автоматическое определение структуры - не нужно вручную описывать реквизиты.
-
Поддержка всех типов документов - работает с любыми конфигурациями.
-
Сохранение иерархии - табличные части сохраняют свою структуру.
-
Готовность к импорту - JSON можно легко загрузить обратно.
-
Стандартные методы работы - используются встроенные средства 1С.
Этап 1: Поиск по метаданным для получения структуры документов
Первым шагом необходимо проанализировать метаданные, чтобы понять структуру каждого типа документа:
&НаСервере
Функция ВыгрузитьСписокВJSONНаСервере(Ссылка)
// Получаем метаданные документа по ссылке
ОбъектМетаданных = Метаданные.НайтиПоТипу(ТипЗнч(Ссылка));
МассивОбработанныхИмен = Новый Массив;
МассивОбработанныхИменТЧ = Новый Массив;
// Формируем список реквизитов для выборки
МассивОбработанныхИмен.Добавить(ОбъектМетаданных.Имя + ".Ссылка КАК Ссылка,");
Для каждого СтрРеквизит Из ОбъектМетаданных.Реквизиты Цикл
МассивОбработанныхИмен.Добавить(ОбъектМетаданных.Имя + "." + СтрРеквизит.Имя +
" КАК " + СтрРеквизит.Имя + ",");
КонецЦикла;
Что здесь происходит:
-
Метаданные.НайтиПоТипу()определяет тип документа по ссылке -
Создаются массивы для хранения имен реквизитов и табличных частей
-
Автоматически собираются все реквизиты документа из метаданных
Этап 2: Формирование динамического запроса с учетом табличных частей
Для табличных частей формируем специальные подзапросы:
// Формируем список табличных частей для выборки
Для каждого СтрТЧ Из ОбъектМетаданных.ТабличныеЧасти Цикл
МассивИменТЧ = Новый Массив;
Для каждого СтрРеквизит Из СтрТЧ.Реквизиты Цикл
МассивИменТЧ.Добавить(СтрРеквизит.Имя + " КАК " + СтрРеквизит.Имя + ",");
КонецЦикла;
// Добавляем номер строки
МассивИменТЧ.Добавить("НомерСтроки КАК НомерСтроки,");
// Убираем последнюю запятую
ИмяБезЗапятой = СтрЗаменить(МассивИменТЧ[МассивИменТЧ.Количество() - 1], ",", "");
МассивИменТЧ.Удалить(МассивИменТЧ.Количество() - 1);
МассивИменТЧ.Добавить(ИмяБезЗапятой);
// Формируем подзапрос для табличной части
МассивОбработанныхИменТЧ.Добавить(ОбъектМетаданных.Имя + "." + СтрТЧ.Имя +
".( " + СтрСоединить(МассивИменТЧ) + " ) КАК " +
СтрТЧ.Имя + ",");
КонецЦикла;
Особенности формирования запроса для табличных частей:
-
Каждая табличная часть становится подзапросом
-
Сохраняется порядок строк через
НомерСтроки -
Автоматически собираются все реквизиты табличной части
Этап 3: Сборка и выполнение итогового запроса
// Формируем и выполняем запрос
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| " + СтрСоединить(МассивОбработанныхИмен) + СтрСоединить(МассивОбработанныхИменТЧ) + "
|ИЗ
| Документ." + ОбъектМетаданных.Имя + " КАК " + ОбъектМетаданных.Имя + "
|ГДЕ
| " + ОбъектМетаданных.Имя + ".Ссылка = &Ссылка";
Запрос.УстановитьПараметр("Ссылка", Ссылка);
Выборка = Запрос.Выполнить().Выгрузить();
Этап 4: Преобразование результатов в удобные структуры
// Преобразуем результат в удобную структуру
Выборка = ОбщегоНазначения.СтрокаТаблицыЗначенийВСтруктуру(Выборка[0]);
// Преобразуем табличные части в массивы
Для каждого Стр Из Выборка Цикл
Если ТипЗнч(Стр.Значение) = Тип("ТаблицаЗначений") Тогда
Выборка[Стр.Ключ] = ОбщегоНазначения.ТаблицаЗначенийВМассив(Стр.Значение);
КонецЕсли;
КонецЦикла;
Возврат Выборка;
КонецФункции
Преобразования данных:
-
СтрокаТаблицыЗначенийВСтруктуру()преобразует строку ТЗ в структуру -
Табличные части преобразуются в массивы структур
-
Получается иерархическая структура, готовая для сериализации в JSON
Этап 5: Сериализация в JSON с иерархической структурой
&НаКлиенте
Асинх Процедура ВыгрузитьСписокВJSON(Команда)
// ... получение пути к файлу
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.ОткрытьФайл(ПутьКФайлу);
// Начинаем запись основного объекта
ЗаписьJSON.ЗаписатьНачалоОбъекта();
ЗаписьJSON.ЗаписатьИмяСвойства("Документы");
ЗаписьJSON.ЗаписатьНачалоМассива();
Для каждого ЭлементСписка Из СписокДокументов Цикл
Ссылка = ЭлементСписка.Значение;
// Получаем данные документа с сервера
Выборка = ВыгрузитьСписокВJSONНаСервере(Ссылка);
ИмяДокумента = ПолучитьИмяДокумента(Ссылка);
// Записываем объект для текущего документа
ЗаписьJSON.ЗаписатьНачалоОбъекта();
ЗаписьJSON.ЗаписатьИмяСвойства(ИмяДокумента);
ЗаписьJSON.ЗаписатьНачалоОбъекта();
// Записываем реквизиты документа
Для каждого Стр1 Из Выборка Цикл
ИмяРеквизита = Стр1.Ключ;
ЗначениеРеквизита = Стр1.Значение;
// Обработка простых реквизитов (не массивов)
Если ТипЗнч(ЗначениеРеквизита) <> Тип("Массив") Тогда
ЗаписьJSON.ЗаписатьИмяСвойства(ИмяРеквизита);
ЗаписьJSON.ЗаписатьЗначение(Строка(ЗначениеРеквизита));
Иначе
// Обработка табличных частей (массивов)
Если ЗначениеРеквизита.Количество() > 0 Тогда
ЗаписьJSON.ЗаписатьИмяСвойства(ИмяРеквизита);
ЗаписьJSON.ЗаписатьНачалоМассива();
// Обработка строк табличной части
Для каждого Стр2 Из ЗначениеРеквизита Цикл
ЗаписьJSON.ЗаписатьНачалоОбъекта();
ЗаписьJSON.ЗаписатьИмяСвойства("Строка");
ЗаписьJSON.ЗаписатьНачалоОбъекта();
// Обработка реквизитов строки табличной части
Для каждого Стр3 Из Стр2 Цикл
ИмяРеквизитаТЧ = Стр3.Ключ;
ЗначениеРеквизитаТЧ = Стр3.Значение;
ЗаписьJSON.ЗаписатьИмяСвойства(ИмяРеквизитаТЧ);
ЗаписьJSON.ЗаписатьЗначение(Строка(ЗначениеРеквизитаТЧ));
КонецЦикла;
ЗаписьJSON.ЗаписатьКонецОбъекта();
ЗаписьJSON.ЗаписатьКонецОбъекта();
КонецЦикла;
ЗаписьJSON.ЗаписатьКонецМассива();
КонецЕсли;
КонецЕсли;
КонецЦикла;
ЗаписьJSON.ЗаписатьКонецОбъекта();
ЗаписьJSON.ЗаписатьКонецОбъекта();
КонецЦикла;
// Завершаем запись JSON
ЗаписьJSON.ЗаписатьКонецМассива();
ЗаписьJSON.ЗаписатьКонецОбъекта();
ЗаписьJSON.Закрыть();
КонецПроцедуры
Импорт
Для демонстрации того, как JSON преобразуется обратно в структуры данных 1С:
&НаКлиенте
Асинх Процедура ЗагрузитьСписокИзJSON(Команда)
// ... получение пути к файлу
// Открываем файл для чтения JSON
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.ОткрытьФайл(ПутьКФайлу);
// Структура JSON автоматически преобразуется в структуры данных 1С
Результат = ПрочитатьJSON(ЧтениеJSON);
//Ваш дальнейший код с обработкой полученной структуры
КонецПроцедуры
Что происходит при импорте:
-
ЧтениеJSONпоследовательно читает JSON-файл -
ПрочитатьJSON()рекурсивно преобразует JSON в структуры 1С:-
JSON-объекты →
Структура -
JSON-массивы →
Массив -
Примитивные значения → соответствующие типы 1С
-
-
Получается иерархическая структура, идентичная исходной
Итоговая структура JSON-файла
{
"Документы": [
{
"ИмяТипаДокумента1": {
"Реквизит1": "Значение1",
"Реквизит2": "Значение2",
"ТабличнаяЧасть1": [
{
"Строка": {
"РеквизитСтроки1": "Значение",
"РеквизитСтроки2": "Значение"
}
}
]
}
}
]
}
Также вопрос к читателям. Когда начал писать импорт, столкнулся с проблемой при автоматическом заполнении/создании документов на основании полученной из .json структуры, код позволяет легко встроить в функцию "ВыгрузитьСписокВJSON" описание типов реквизитов, с примитивными типами все легко, но с ссылочными типами сложнее. Когда использую метод "ТипЗнч()", то если это ссылочный тип, он выглядит, например, так: "Авансовый отчет", плюс в .json это просто строка и когда я обрабатываю .json, то очевидно не получается с помощью строки "Авансовый отчет" найти необходимые метаданные сначала по типу, а потом найти ссылку для реквизита. Так вот вопрос, как лучше записывать типы реквизитов в .json, чтобы потом по этим типам искать ссылки или придется писать хитрую процедуру определения типа реквизита по тому, что есть?
Проверено на следующих конфигурациях и релизах:
- 1С:ERP Управление предприятием 2, релизы 2.5.22.131
Вступайте в нашу телеграмм-группу Инфостарт
