XML в JSON: это сложнее, чем выглядит
Почему конвертация между XML и JSON производит неожиданные результаты, и как обрабатывать крайние случаи.
У тебя есть XML-данные. Твоему JavaScript-приложению нужен JSON. Конвертируй и двигайся дальше, правильно?
Но конвертация производит неожиданные результаты. Массивы, которые должны существовать, не существуют. Атрибуты оказываются в странных местах. Одиночные элементы становятся массивами случайно.
XML и JSON моделируют данные по-разному. Конвертация между ними требует решений.
Фундаментальное несоответствие
В JSON есть: объекты, массивы, строки, числа, булевы значения, null.
В XML есть: элементы, атрибуты, текстовое содержимое, пространства имён, комментарии, CDATA.
Нет взаимно однозначного соответствия.
Проблема массивов
В XML нет массивов. Есть повторяющиеся элементы.
<users>
<user>Alice</user>
<user>Bob</user>
</users>
Это, вероятно, должно стать:
{"users": {"user": ["Alice", "Bob"]}}
Но что насчёт:
<users>
<user>Alice</user>
</users>
Один элемент. Это массив с одним элементом или просто строка? Разные конвертеры решают по-разному.
Консистентность важна. Если user иногда массив, а иногда строка, твой код ломается.
Проблема атрибутов
В XML есть атрибуты. В JSON нет.
<product id="123">Widget</product>
Распространённые стратегии конвертации:
{"product": {"_id": "123", "_text": "Widget"}}
{"product": {"@id": "123", "#text": "Widget"}}
{"product": {"$": {"id": "123"}, "_": "Widget"}}
Каждое соглашение отличается. Знай, что производит твой конвертер.
Проблема пространств имён
XML пространства имён создают квалифицированные имена типа soap:Envelope. В JSON нет концепции пространств имён.
Конвертеры либо:
- Включают префиксы в имена свойств:
"soap:Envelope" - Убирают префиксы:
"Envelope" - Создают вложенные структуры для обработки пространств имён
У каждого подхода есть компромиссы.
Практические советы
Будь консистентным. Выбери библиотеку конвертации и придерживайся её. Смешивание конвертеров производит несогласованные структуры.
Форсируй массивы. Если элемент может иметь несколько экземпляров, настрой конвертер всегда производить массивы, даже для одиночных элементов.
Тестируй крайние случаи. Конвертируй реальные данные, а не только образцы. Крайние случаи в продакшн-данных тебя удивят.
Рассмотри альтернативы. Если ты контролируешь оба конца, рассмотри использование JSON с самого начала. Конвертация туда-сюда теряет информацию.
Проблемы JSON в XML
Идти в другую сторону тоже имеет проблемы.
Нет представления массива. JSON-массивы становятся повторяющимися элементами. Тебе нужно назвать эти элементы.
{"items": [1, 2, 3]}
Становится чем? <items><item>1</item>...</items>? Откуда берётся "item"?
Типы чисел. JSON различает числа и строки. XML не различает. 123 может стать <value>123</value> — это число или строка?
Когда конвертировать
Интеграция с унаследованными системами. SOAP API и старые корпоративные системы используют XML. Конвертируй на границе.
Обработка XML-данных. JavaScript обрабатывает JSON гораздо лучше, чем XML. Конвертируй, обрабатывай, конвертируй обратно, если нужно.
Одноразовые миграции. Переход от XML-основанных систем к JSON-основанным.
Когда не конвертировать
Требования round-trip. XML → JSON → XML часто теряет информацию. Атрибуты, пространства имён, порядок.
Валидация схемы. У XML есть мощные языки схем (XSD). JSON Schema менее зрелый.
Обработка документов. Модель смешанного контента XML (текст со встроенными элементами) не отображается на JSON чисто.
XML и JSON представляют данные по-разному. Конвертация требует выбора относительно массивов, атрибутов и пространств имён. Пойми поведение своего конвертера и тестируй с реалистичными данными.