Как в 1С преобразовать строку JSON в формат XML?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

Задача преобразования данных из формата JSON в XML является классической при интеграции "1С:Предприятия" с внешними веб-сервисами, сайтами или устаревшими системами, которые принимают данные только в формате XML. В этой статье мы подробно разберем, как реализовать этот механизм, проанализируем распространенные ошибки (включая те, что допускают нейросети при генерации кода) и рассмотрим два основных подхода: автоматический через XDTO и ручной через потоковую запись. С этой задачей также отлично справляется модуль «Трансформер» для конвертации JSON/XML/CSV/TOON, который расширяет стандартные возможности платформы по работе с различными форматами.

Почему возникает сложность?

Казалось бы, оба формата иерархичны. Однако между ними есть существенные различия:

  1. Корневой элемент: В XML обязан быть один корневой тег. В JSON корнем может быть массив или объект без имени. Перед началом преобразования бывает полезно провести проверку на заполненность обязательных полей в строке JSON, чтобы гарантировать корректность входящих данных.
  2. Типы данных: JSON оперирует строками, числами, булево, null, массивами и объектами. В XML все является текстом, если не подключена XSD-схема, а даты требуют специфического форматирования.
  3. Атрибуты: В XML есть элементы и атрибуты элементов. В JSON — только пары "ключ-значение".

Давайте рассмотрим, как эти препятствия можно преодолеть средствами платформы 1С.

Способ №1: Использование Сериализатора XDTO (Автоматический метод)

Если ваша задача — быстро преобразовать данные, и вам не критически важна структура выходного XML (или она стандартная для 1С), то лучшим выбором будет использование объекта СериализаторXDTO. Этот метод позволяет платформе самой решать, как сопоставить типы. При работе со сложными сторонними API часто требуется предварительная конвертация схемы XSD в модель XDTO, чтобы типизация данных прошла без ошибок.

Рассмотрим алгоритм действий:

  1. Мы читаем JSON в объект XDTO.
  2. Мы записываем полученный объект XDTO в XML.

Посмотрим на пример кода, реализующего этот подход:


Функция ПреобразоватьJSONвXML_XDTO(ТекстJSON) Экспорт
	
	// 1. Читаем JSON
	ЧтениеJSON = Новый ЧтениеJSON;
	ЧтениеJSON.УстановитьСтроку(ТекстJSON);
	
	// Используем глобальную фабрику XDTO или созданную специально под задачу
	// Читаем JSON сразу в объект XDTO
	ОбъектXDTO = СериализаторXDTO.ПрочитатьJSON(ЧтениеJSON);
	
	ЧтениеJSON.Закрыть();
	
	// 2. Записываем в XML
	ЗаписьXML = Новый ЗаписьXML;
	ЗаписьXML.УстановитьСтроку(); // Пишем в память (в строку)
	
	// Сериализуем объект XDTO в XML
	СериализаторXDTO.ЗаписатьXML(ЗаписьXML, ОбъектXDTO);
	
	РезультатXML = ЗаписьXML.Закрыть();
	
	Возврат РезультатXML;
	
КонецФункции

Преимущества: Код занимает минимум строк, платформа берет на себя экранирование спецсимволов и обработку базовых типов.

Недостатки: Вы получаете XML в специфическом формате 1С (с пространствами имен xs:, xsi:), который может не подойти, если внешняя система требует строго определенную структуру.

Способ №2: Ручной парсинг (Потоковое чтение и запись)

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

Логика работы будет следующей:

  1. Читаем JSON в нативные коллекции 1С (Структура, Массив) с помощью метода ПрочитатьJSON.
  2. Создаем объект ЗаписьXML.
  3. Вручную создаем корневой элемент (так как в JSON его может не быть).
  4. Запускаем рекурсивную процедуру, которая обходит дерево данных и пишет соответствующие теги XML.

Разберем этот процесс по шагам.

Шаг 1: Подготовка функции конвертации

Сначала напишем основную функцию, которая инициализирует чтение и запись.


Функция ПреобразоватьJSONвXML_Ручной(ТекстJSON) Экспорт
	
	// 1. Парсим JSON в структуру/массив 1С
	ЧтениеJSON = Новый ЧтениеJSON;
	ЧтениеJSON.УстановитьСтроку(ТекстJSON);
	
	// Функция ПрочитатьJSON вернет Структуру, Массив или примитивный тип
	// в зависимости от содержимого
	ДанныеJSON = ПрочитатьJSON(ЧтениеJSON);
	ЧтениеJSON.Закрыть();
	
	// 2. Подготовка записи XML
	ЗаписьXML = Новый ЗаписьXML;
	ЗаписьXML.УстановитьСтроку();
	
	// Добавляем заголовок XML <?xml version="1.0"?>
	ЗаписьXML.ЗаписатьОбъявлениеXML();
	
	// ВАЖНО: XML требует одного корневого элемента.
	// В JSON его может не быть, поэтому создадим искусственный корень "Root"
	ЗаписьXML.ЗаписатьНачалоЭлемента("Root");
	
	// 3. Запускаем рекурсивный обход
	ОбходДереваJSON(ЗаписьXML, ДанныеJSON, "Item");
	
	// Закрываем корень
	ЗаписьXML.ЗаписатьКонецЭлемента(); // </Root>
	
	Возврат ЗаписьXML.Закрыть();
	
КонецФункции

Шаг 2: Реализация рекурсивного обхода

Теперь самое интересное. Нам нужна процедура ОбходДереваJSON, которая сможет переварить любую вложенность. Она должна определять тип текущего узла и действовать соответственно:

Давайте напишем этот код подробно:


// Процедура рекурсивного обхода
Процедура ОбходДереваJSON(ЗаписьXML, Значение, Знач ИмяТэга = "")
	
	ТипЗначения = ТипЗнч(Значение);
	
	Если ТипЗначения = Тип("Структура") Тогда
		Для Каждого ЭлементСтруктуры Из Значение Цикл
			ЗаписьXML.ЗаписатьНачалоЭлемента(ЭлементСтруктуры.Ключ);
			ОбходДереваJSON(ЗаписьXML, ЭлементСтруктуры.Значение, ЭлементСтруктуры.Ключ);
			ЗаписьXML.ЗаписатьКонецЭлемента();
		КонецЦикла;
		
	ИначеЕсли ТипЗначения = Тип("Массив") Тогда
		ИмяЭлементаМассива = ?(ПустаяСтрока(ИмяТэга), "Item", ИмяТэга);
		Для Каждого ПодЭлемент Из Значение Цикл
			Если ТипЗнч(ПодЭлемент) = Тип("Структура") Тогда
				ЗаписьXML.ЗаписатьНачалоЭлемента("Item");
				ОбходДереваJSON(ЗаписьXML, ПодЭлемент);
				ЗаписьXML.ЗаписатьКонецЭлемента();
			Иначе
				ЗаписьXML.ЗаписатьНачалоЭлемента("Item");
				ЗаписьXML.ЗаписатьТекст(Строка(ПодЭлемент));
				ЗаписьXML.ЗаписатьКонецЭлемента();
			КонецЕсли;
		КонецЦикла;
		
	Иначе
		ТекстДляЗаписи = "";
		Если ТипЗначения = Тип("Дата") Тогда
			ТекстДляЗаписи = XMLСтрока(Значение); 
		ИначеЕсли ТипЗначения = Тип("Булево") Тогда
			ТекстДляЗаписи = ?(Значение, "true", "false");
		Иначе
			ТекстДляЗаписи = Строка(Значение);
		КонецЕсли;
		
		ЗаписьXML.ЗаписатьТекст(ТекстДляЗаписи);
	КонецЕсли;
	
КонецПроцедуры

Обратите внимание: Приведенный выше код рекурсии требует тонкой настройки под конкретную задачу. Главная проблема конвертации JSON -> XML — это неоднозначность массивов. В нашем примере мы использовали подход с вложенными Item, чтобы гарантировать валидность структуры.

Ошибки, которых следует избегать

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

  1. СтруктураJSON.ПрочитатьИзСтроки(JSONСтрока) — у объекта ЧтениеJSON нет такого метода.
  2. XMLДокумент = Новый XMLДокумент — в 1С объект ДокументDOM существует, но используется для построения дерева в памяти, что сложнее и медленнее для простых задач.
  3. ДобавитьЭлемент() — у ЗаписьXML нет такого метода. Есть ЗаписатьНачалоЭлемента().

Рекомендации

Если вам нужно просто сохранить данные для другой системы 1С — используйте СериализаторXDTO. Это сэкономит часы работы.

Если вам нужно отправить данные в банк, госорган или стороннее API, требующее жесткой схемы — используйте ЗаписьXML и ручной обход. В случаях, когда полученный XML необходимо представить в читаемом виде для пользователя, вы можете узнать, как превратить скучный XML в красивый отчет через XSLT в 1С. Это позволит вам контролировать каждый тэг, атрибут и визуализацию данных.

← На главную