Загрузка JSON в дерево значений

29.06.21

Разработка - Универсальные функции

Читаем и парсим JSON, засовываем его в дерево - что тут сложного?

Скачать исходный код

Наименование Файл Версия Размер
Загрузка JSON в дерево значений:
.epf 7,05Kb
12
.epf 0.1 7,05Kb 12 Скачать

JSON -> ДЕРЕВО ЗНАЧЕНИЙ

 

ВВЕДЕНИЕ

Некоторые уже стали забывать, а некоторые даже и не знали (вот я, например), что JSON - это JavaScript Object Notation, что переводится примерно как "'Запись' объекта в JavaScript". Честно говоря, слово "нотация" вроде как можно и не переводить - оно уже входит в русский язык, но в данном случае это именно "запись", т.е. представление объекта в виде некой структурированной записи - структуры данных, а в данном конкретном случае еще и характерная для JavaScript.

Сейчас JSON используется далеко за пределами JS, парсеры для JSON появились даже в 1С и представляют из себя мало отличимый от персера XML список объектов для повседневного использования.

 

ПАРСЕР JSON В 1С 

Здесь, как и в XML, есть два простых базовых объекта для чтения и записи JSON. Вот они:

Запись = Новый ЗаписьJSON;
Чтение = Новый ЧтениеJSON;

 Собственно, работа с этими объектами в обычном повседневном применении проста до безобразия:

// Читаем JSON

Чтение.УстановитьСтроку( СтрокаJSON ); // строка, которая прилетела к вам из какого-нибудь сервиса
ДанныеСтруктура = ПрочитатьJSON( Чтение);
ДанныеСоответствие = ПрочитатьJSON( Чтение, Истина );

// Пишем JSON

Запись.УстановитьСтроку();
ЗаписатьJSON( Запись, ДанныеСтруктура ); // значением может быть простой тип, структура и соответствие
СтрокаJSON = Запись.Закрыть();

JSON в 1С может быть прочитан в структуру или соответствие ("Истина" во втором параметре как раз говорит, чтобы система прочитала данные в соответствие). Также если в данных есть даты, то имена этих полей нужно указать в следующем параметре. Там есть еще некоторое количество параметров, которые могут пригодиться вам, если вдруг вы захотите записать что-то помимо простых типов, массивов, структур, соответствий и их фиксированных вариантов.

При записи JSON может быть преобразован простой тип, структура, соответствие, дата и т.д. = здесь уже не надо заморачиваться со списком полей и видом преобразование. А если вы хотите записать что-то помимо этого, то, опять же, вам помогут дополнительные параметры с указанием функции преобразования.

Надеюсь, что с чтением и записью мы разобрались. Давайте превратим этот набор данных в дерево. Т.е. мы сделаем дерево из структуры (кто хочет - может сделать дерево и из соответствия - даже код менять не нужно).

 

В ДЕРЕВО!

Ну код тут прост, как три копейки...

&НаСервере
Процедура ПоместитьВДерево( Текст )
	Чтение = Новый ЧтениеJSON;
	Чтение.УстановитьСтроку( Текст );
	Данные = ПрочитатьJSON( Чтение );
	
	ЗначениеВРеквизитФормы(
		РазвернутьВДерево( РеквизитФормыВЗначение("Дерево"), Данные ),
		"Дерево" );
	
КонецПроцедуры
	
&НаСервереБезКонтекста
Функция РазвернутьВДерево( Дерево, Данные, Параметр = "" )
	Для Каждого Ст ИЗ Данные Цикл 
		Если ТипЗнч(Ст) = Тип("КлючИЗначение") Тогда 
			Строка = Дерево.Строки.Добавить();
			Строка.Параметр = Ст.Ключ;
			Если ТипЗнч(Ст.Значение) = Тип("Структура") 
				ИЛИ ТипЗнч(Ст.Значение) = Тип("Массив") Тогда 
				РазвернутьВДерево( Строка, Ст.Значение, Ст.Ключ );
			Иначе
				Строка.Значение =  Ст.Значение
			КонецЕсли;
		Иначе
			Строка = Дерево.Строки.Добавить();
			Строка.Параметр = Параметр;
			Если ТипЗнч(Ст) = Тип("Структура") 
				ИЛИ ТипЗнч(Ст) = Тип("Массив") Тогда 
				РазвернутьВДерево( Строка, Ст, Параметр );
			Иначе
				Строка.Значение =  Ст
			КонецЕсли;
		КонецЕсли;
	КонецЦикла;
	Возврат Дерево
КонецФункции

На выходе у нас что-то типа этого:

Исходный файл вот такой (начало):

{"dox":{"tux":{"res":[{
"part":{"xtd":"320565","godex":{"name":"TE Connectivity"},
"ibo":[{
"hado":{"name":"oxford"},"hubos":[{
[...]

В общем, пробуйте, уважаемые господа-товарищи - обработка прикреплена.

PS: в справке 1С написано, что данный функционал доступен с 8.3.6, но тестировалась обработка на 8.3.18.1289.

JSON парсинг дерево значений

См. также

Вставляем картинку из буфера обмена (платформа 1С 8.3.24)

Универсальные функции Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

Задача: вставить картинку из буфера обмена на форму средствами платформы 1С.

1 стартмани

18.03.2024    2880    2    John_d    11    

56

GUID в 1С 8.3 - как с ними быть

Универсальные функции Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Пришлось помучиться с GUID-ами немного, решил поделиться опытом, мало ли кому пригодится.

12.02.2024    5025    atdonya    22    

51

Переоткрытие внешних обработок

Универсальные функции Платформа 1С v8.3 Бесплатно (free)

На заключительных этапах, когда идет отладка или доработка интерфейса, необходимо много раз переоткрыть внешний объект. Вот один из способов автоматизации этого.

30.11.2023    4099    ke.92@mail.ru    16    

62

Валидация JSON через XDTO (включая массивы)

WEB-интеграция Универсальные функции Механизмы платформы 1С Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

При работе с интеграциями рано или поздно придется столкнуться с получением JSON файлов. И, конечно же, жизнь заставит проверять файлы перед тем, как записывать данные в БД.

28.08.2023    9359    YA_418728146    6    

143

Печать непроведенных документов для УТ, КА, ERP. Настройка печати по пользователям, документам и печатным формам

Пакетная печать Печатные формы Адаптация типовых решений Универсальные функции Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Россия Абонемент ($m)

Расширение для программ 1С:Управление торговлей, 1С:Комплексная автоматизация, 1С:ERP, которое позволяет распечатывать печатные формы для непроведенных документов. Можно настроить, каким пользователям, какие конкретные формы документов разрешено печатать без проведения документа.

2 стартмани

22.08.2023    2213    24    progmaster    7    

3

Расширение: Быстрые отборы через буфер [Alt+C] Копировать список, [Alt+V] Вставить список, [Ctrl+C] Копировать из файлов

Инструментарий разработчика Универсальные функции Платформа 1С v8.3 Конфигурации 1cv8 1С:Розница 2 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Зарплата и Управление Персоналом 3.x Абонемент ($m)

Копирует в буфер значения из списков, из ячеек отчетов, таблиц, настроек списков, других отборов и вставляет в выбранную настройку отбора. Работает с Объект не найден. Работает как в одной так и между разными базами 1С. Использует комбинации [Alt+C] Копировать список, [Alt+V] Вставить список. Также для копирования данных используется стандартная [Ctrl+C] (например из открытого xls, mxl, doc и т.п. файла скопировать список наименований)

1 стартмани

13.10.2022    16342    142    sapervodichka    112    

130

Система контроля ведения учета [БСП]

Универсальные функции Механизмы типовых конфигураций БСП (Библиотека стандартных подсистем) Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

В данном материале рассмотрим типовой алгоритм подсистемы контроля учета БСП в конфигурациях на примерах.

18.07.2022    7349    quazare    8    

110
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. aleksey2 86 30.06.21 08:15 Сейчас в теме
начиная с платформы 8.3.6.1977
+
2. ITSun 28.07.21 08:23 Сейчас в теме
Тренируетесь?

Физкультура - это хорошо!
И рейтинг опять же.
+
3. starik-2005 3036 28.07.21 11:53 Сейчас в теме
(2)
Тренируетесь
Типа того. Реакция на одного неадеквата в действительности.
+
5. RustIG 1556 02.12.21 01:13 Сейчас в теме
кажется дерево содержит лишние узлы - см. картинку
Прикрепленные файлы:
+
7. starik-2005 3036 02.12.21 23:30 Сейчас в теме
6. RustIG 1556 02.12.21 14:13 Сейчас в теме
создание дерева через рекурсию
Процедура СоздатьДерево(Кнопка)
	
	Чтение = Новый ЧтениеJSON;
	Чтение.УстановитьСтроку(ЭлементыФормы.ПолеТекстовогоДокумента1.ПолучитьТекст());
	Данные = ПрочитатьJSON(Чтение);
	
	Дерево = Новый ДеревоЗначений;
	Дерево.Колонки.Добавить("Параметр");
	Дерево.Колонки.Добавить("Значение");
	
	ТекУзел = Дерево;
		
	ДобавитьУзел(ТекУзел, Данные);
	
	ЭлементыФормы.Дерево.СоздатьКолонки();	

КонецПроцедуры

Процедура ДобавитьУзел(ТекУзел, СтруктураДерева)
		
	Для Каждого ЭлСтруктуры Из СтруктураДерева Цикл
		
		Если ТипЗнч(СтруктураДерева)=Тип("Структура") Тогда			
 
			ПодчиненныйУзел = ТекУзел.Строки.Добавить();
			ПодчиненныйУзел.Параметр = ЭлСтруктуры.Ключ;
			
			Если ТипЗнч(ЭлСтруктуры.Значение)=Тип("Структура") 
				ИЛИ ТипЗнч(ЭлСтруктуры.Значение)=Тип("Массив") Тогда
				ДобавитьУзел(ПодчиненныйУзел, ЭлСтруктуры.Значение);
			Иначе
				ПодчиненныйУзел.Значение = ЭлСтруктуры.Значение;
			КонецЕсли; 		
			
		Иначе //массив
			
			//ПодчиненныйУзел = ТекУзел.Строки.Добавить();
			//ПодчиненныйУзел.Параметр = ЭлСтруктуры;
			
			Если ТипЗнч(ЭлСтруктуры)=Тип("Структура") 
				ИЛИ ТипЗнч(ЭлСтруктуры)=Тип("Массив") Тогда
				ДобавитьУзел(ТекУзел, ЭлСтруктуры);
			Иначе
				ПодчиненныйУзел.Значение = ЭлСтруктуры;
			КонецЕсли; 		
			
		КонецЕсли;
			
	КонецЦикла;
		
КонецПроцедуры
Показать
Прикрепленные файлы:
+
8. miXna5 72 06.12.21 17:08 Сейчас в теме
(6) У вас добавляются только узлы 1 уровня. Если подчиненность идет дальше, будет выводиться неверно (без вложенности). У автора поста отрабатывает нормально.
+
9. RustIG 1556 06.12.21 18:33 Сейчас в теме
10. miXna5 72 20.12.21 14:25 Сейчас в теме
(9) Вот пример. На прикрепленных скриншотах результат выполнения по методу автора и по вашему.
По методу автора массив элементов, которые состоят в свою очередь из объектов разложится наглядно в структуры, а по вашей процедуре свойства объектов в массиве будут выводится общим списком, что не наглядно.
Дело как раз в двух закомментированных строках.
Прикрепленные файлы:
+
11. RustIG 1556 20.12.21 15:08 Сейчас в теме
(10) можете прислать файл json? хочу сам отладить
+
12. miXna5 72 20.12.21 16:16 Сейчас в теме
(11) Мне это API портала "Электронный знак" (Белорусский аналог Честного знака) возвращает. Сохранил в файл.
Прикрепленные файлы:
Пример.json
+
13. RustIG 1556 20.12.21 18:13 Сейчас в теме
(12) спасибо.
разобрался.
моей целью было - как можно точнее отобразить содержимое файла джейсон
вот сравните результат моего алгоритма и содержимое файла джейсон
Прикрепленные файлы:
+
14. RustIG 1556 20.12.21 18:24 Сейчас в теме
(12) один файл джейсон можно сгенерировать несколькими алгоритмами, при этом несколько по-разному связанных таблиц в базе данных можно отобразить одним и тем же файлом джейсон.... файл джейсон призван передать в сжатом виде информацию только в одну сторону. Каким образом расшифровывать полученный файл - это уже задача интерпретатора, и можно использовать как алгоритм Сергея Андреева, так и мой вариант. В его алгоритме надо "держать в уме" что повторяющиеся узлы "params" - это не элемент структуры, а очередной элемент списка (!)...
В моем варианте нужно "держать в уме" что повторяющиеся элементы списка не обрамлены структурно в узлы, а идут последовательно друг за другом....
Это как расшифровка xml-файла - алгоритм расшифровки всегда уникален и индивидуален.
Вообще,я думаю, можно найти золотую середину - компромисс - использовать алгоритм варианта 3 (!) - мы структурно выделяем элементы списка, но в названии узла используем префикс или суффикс - отличающий наш "1с-овский" узел - например "params1","params2", "params3", "держа в уме" что одноименные параметры - это всегда элементы списка, а номер параметра это порядковый номер...
+
15. RustIG 1556 20.12.21 18:45 Сейчас в теме
(12) или еще вариант - мы все привыкли что для отображения джейсон -структуры можно использовать Дерево с двумя полями (!):
 Дерево = Новый ДеревоЗначений;
	Дерево.Колонки.Добавить("Параметр");
	Дерево.Колонки.Добавить("Значение");

Я предлагаю использовать три поля - добавить еще "ТипЭлемента": значениями будут "УзелСтруктуры" или "ЭлементСписка" ("ЭлементМассива"):

 Дерево = Новый ДеревоЗначений;
	Дерево.Колонки.Добавить("Параметр");
	Дерево.Колонки.Добавить("Значение");
       Дерево.Колонки.Добавить("ТипЭлемента");

Это для моего варианта алгоритма и для варианта Сергея Андреева - будет полезно, чтобы была однозначная интерпретация.
+
16. RustIG 1556 20.12.21 18:49 Сейчас в теме
(12) в целом , спасибо за активное участие! я для себя понял гораздо больше нюансов джейсон-структур.
+
17. RustIG 1556 20.12.21 19:33 Сейчас в теме
(12) готово!
вот код:
Процедура СоздатьДерево(Кнопка)
	
	Чтение = Новый ЧтениеJSON;
	Чтение.УстановитьСтроку(ЭлементыФормы.ПолеТекстовогоДокумента1.ПолучитьТекст());
	Данные = ПрочитатьJSON(Чтение);
	
	//Для Каждого Ст ИЗ Данные Цикл 
	//	Если ТипЗнч(Ст) = Тип("КлючИЗначение") Тогда 
	//		Строка = Дерево.Строки.Добавить();
	//		Строка.Параметр = Ст.Ключ;
	//		Если ТипЗнч(Ст.Значение) = Тип("Структура") 
	//			ИЛИ ТипЗнч(Ст.Значение) = Тип("Массив") Тогда 
	//			РазвернутьВДерево( Строка, Ст.Значение, Ст.Ключ );
	//		Иначе
	//			Строка.Значение =  Ст.Значение
	//		КонецЕсли;
	//	Иначе
	//		Строка = Дерево.Строки.Добавить();
	//		Строка.Параметр = Параметр;
	//		Если ТипЗнч(Ст) = Тип("Структура") 
	//			ИЛИ ТипЗнч(Ст) = Тип("Массив") Тогда 
	//			РазвернутьВДерево( Строка, Ст, Параметр );
	//		Иначе
	//			Строка.Значение =  Ст
	//		КонецЕсли;
	//	КонецЕсли;
	//КонецЦикла;	

	Дерево = Новый ДеревоЗначений;
	Дерево.Колонки.Добавить("Параметр");
	Дерево.Колонки.Добавить("Значение");
	Дерево.Колонки.Добавить("ТипЭлемента");
	
	ТекУзел = Дерево;
		
	ДобавитьУзел(ТекУзел, Данные);
	
	ЭлементыФормы.Дерево.СоздатьКолонки();	

КонецПроцедуры

Процедура ДобавитьУзел(ТекУзел, СтруктураДерева, ТипЭлемента = "")
		
	Для Каждого ЭлСтруктуры Из СтруктураДерева Цикл
		
		Если ТипЗнч(СтруктураДерева)=Тип("Структура") Тогда			
			
			ТипЭлемента = ТипЗнч(ЭлСтруктуры.Значение);
			
			ПодчиненныйУзел = ТекУзел.Строки.Добавить();
			ПодчиненныйУзел.Параметр = ЭлСтруктуры.Ключ;
			ПодчиненныйУзел.ТипЭлемента = ТипЭлемента;
			
			Если ТипЭлемента=Тип("Структура") ИЛИ ТипЭлемента=Тип("Массив") Тогда
				ДобавитьУзел(ПодчиненныйУзел, ЭлСтруктуры.Значение, ТипЭлемента);
			Иначе
				ПодчиненныйУзел.Значение = ЭлСтруктуры.Значение;
			КонецЕсли; 		
			
		Иначе //массив
			
			ТипЭлемента = ТипЗнч(ЭлСтруктуры);
			
			ПодчиненныйУзел = ТекУзел.Строки.Добавить();
			ПодчиненныйУзел.Параметр = "" + ЭлСтруктуры + СтруктураДерева.Найти(ЭлСтруктуры);
			ПодчиненныйУзел.ТипЭлемента = ТипЭлемента;    			

			Если ТипЭлемента=Тип("Структура") ИЛИ ТипЭлемента=Тип("Массив") Тогда
				ДобавитьУзел(ТекУзел, ЭлСтруктуры, ТипЭлемента);
			Иначе
				ПодчиненныйУзел.Значение = ЭлСтруктуры;
				ПодчиненныйУзел.ТипЭлемента = ТипЭлемента;
			КонецЕсли; 		
			
		КонецЕсли;
			
	КонецЦикла;
		
КонецПроцедуры

Показать


результат в картинках
Прикрепленные файлы:
miXna5; +1
Оставьте свое сообщение