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

29.06.21

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

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

Файлы

ВНИМАНИЕ: Файлы из Базы знаний - это исходный код разработки. Это примеры решения задач, шаблоны, заготовки, "строительные материалы" для учетной системы. Файлы ориентированы на специалистов 1С, которые могут разобраться в коде и оптимизировать программу для запуска в базе данных. Гарантии работоспособности нет. Возврата нет. Технической поддержки нет.

Наименование Скачано Купить файл
Загрузка JSON в дерево значений:
.epf 7,05Kb ver:0.1
15 2 500 руб. Купить

Подписка PRO — скачивайте любые файлы со скидкой до 85% из Базы знаний

Оформите подписку на компанию для решения рабочих задач

Оформить подписку и скачать решение со скидкой

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 парсинг дерево значений

См. также

Загрузка и выгрузка в Excel Универсальные функции Программист 1С:Предприятие 8 Россия Бесплатно (free)

Описанный ниже подход позволяет в три шага заполнять формулы в Excel файлы, вне зависимости от ОС сервера (MS Windows Server или Linux). Подход подразумевает отказ от работы с COM-объектом в пользу работы через "объектную модель документа" (DOM).

30.10.2025    4110    Abysswalker    10    

46

Универсальные функции Работа с интерфейсом Программист 1С:Предприятие 8 Бесплатно (free)

Порой необходимо временно отключить расширение 1С, не удаляя его, чтобы не потерять данные. Но в этом случае при каждом запуске всем будет лезть уведомление о неактивном расширении, хотя очевидно, это техническая информация, которой не стоит лишний раз пугать пользователей.

14.05.2025    7662    DeerCven    15    

61

Универсальные функции Программист 1С:Предприятие 8 1C:Бухгалтерия Бесплатно (free)

Благодаря этим пяти строчкам можно больше не заморачиваться с загрузкой из внешних файлов. Пользуюсь везде, всегда и постоянно.

21.05.2024    52630    dimanich70    84    

174

Универсальные функции Программист 1С:Предприятие 8 1C:Бухгалтерия Абонемент ($m)

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

1 стартмани

18.03.2024    7665    7    John_d    13    

59

Универсальные функции Программист Стажер 1С:Предприятие 8 1C:Бухгалтерия Бесплатно (free)

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

12.02.2024    67111    atdonya    31    

72

Универсальные функции Программист 1С:Предприятие 8 Бесплатно (free)

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

30.11.2023    9592    ke.92@mail.ru    17    

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

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

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

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

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

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

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

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

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

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

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

Показать


результат в картинках
Прикрепленные файлы:
igor-pn; miXna5; +2 Ответить
18. ablent 25 12.04.25 21:24 Сейчас в теме
Доработал вторую процедуру для работы с соответствием
Процедура ДобавитьУзел(ТекУзел, СтруктураДерева, ТипЭлемента = "")
        
    Для Каждого ЭлСтруктуры Из СтруктураДерева Цикл
        
        Если ТипЗнч(СтруктураДерева)=Тип("Структура") Тогда            
            
            ТипЭлемента = ТипЗнч(ЭлСтруктуры.Значение);
            
            ПодчиненныйУзел = ТекУзел.Строки.Добавить();
            ПодчиненныйУзел.Параметр = ЭлСтруктуры.Ключ;
            ПодчиненныйУзел.ТипЭлемента = ТипЭлемента;
            
			Если ТипЭлемента=Тип("Структура") 
				ИЛИ ТипЭлемента=Тип("Массив") 
				ИЛИ ТипЭлемента=Тип("Соответствие") Тогда

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

			Если ТипЭлемента=Тип("Структура") 
				ИЛИ ТипЭлемента=Тип("Массив")
				ИЛИ ТипЭлемента=Тип("Соответствие") Тогда

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