Введение Что такого замечательного в XML? Он реализован для всех платформ, «человекочитаемый», для него созданы схемы данных (условно человекочитаемые).
Открывая в браузере 25-мегабайтный файл, сразу замечаешь недостатки этого текстового формата и начинаешь об этом задумываться.
Мы, конечно, не часто это делаем, но все же, чем мы могли бы заменить XML? Добавление в проект самодельных бинарных контейнеров заканчивается провалом, когда к вам приходят партнеры и просят подключить их к этому каналу данных.
Google Protobuf на первый взгляд выглядит хорошо, но вскоре вы понимаете, что он не является заменой XML и ему не хватает функциональности.
BSON в 5 раз медленнее Protobuf, менее компактен и для него не реализованы схемы данных.
Давайте разработаем другой двоичный формат. Доллар США 1.0 USDS (или $S) — Универсальные сериализованные структуры данных — универсальные сериализованные структуры данных, двоичный формат, способный полностью заменить XML и JSON. Основные отличия:
- Вместо текстовых тегов/ключей используются целые числа.
Связь «Имя» - «Целый идентификатор» указывается отдельно, в «Словаре».
Словарь можно прикрепить к документу USDS или передать отдельно.
- Здесь нет закрывающих тегов, как в XML;
- Документы USDS формируются строго по схеме, которая также указана в Словаре.
Поддерживаются полиморфизм и необязательные поля.
- Числовые значения в документе USDS хранятся в двоичном виде (а не в виде текста).
Есть ли прибыль? Контрольный показатель расставлю все на свои места:
Что-то в этом уже есть, хотя работы еще много: Basic Parser всегда будет уступать Google Protobuf, но не настолько.
Пример использования Хотя формат является двоичным, использовать его не сложнее, чем XML. Посмотрим, как это будет выглядеть на C++ (и в далеком светлом будущем на других языках).
Шаг 1: составьте словарь
Как указано выше, документ USDS построен только по схеме, которая может выглядеть так:Все правила построения схемы можно посмотреть Здесь .USDS DICTIONARY ID=1000000 v.1.0 { 1: STRUCT internalObject { 1: UNSIGNED VARINT varintField; 1: UNSIGNED VARINT varintField; 2: DOUBLE doubleField; 3: STRING<UTF-8> stringField; 4: BOOLEAN booleanField; } RESTRICT {notRoot;} 2: STRUCT rootObject { 1: INT intField; 2: LONG longField; 3: ARRAY<internalObject> arrayField; } }
Библиотека USDS Basic Parser пока не поддерживает все элементы схемы, но пример выше работает. Сохраняем диаграмму в текстовый файл, либо вставляем прямо в исходный код, что дальше?
Шаг 2: инициализируйте парсер:
Так или иначе, схема данных оказалась в массиве text_dictionary, скормим ее парсеру: BasicParser* clientParser = new BasicParser();
clientParser->addDictionaryFromText(text_dictionary, strlen(text_dictionary), USDS_UTF8);
Парсер готов генерировать бинарные документы USDS. Если вам нужно только декодировать двоичные файлы, то инициализация со словарем не требуется: парсер автоматически вытащит словарь непосредственно из двоичного документа USDS.
Шаг 3: создайте двоичный документ:
Алгоритм ничем не отличается от работы с любым другим парсером DOM: добавляем несколько корневых объектов, инициализируем их значениями и генерируем выходной массив данных.
UsdsStruct* tag = clientParser->addStructTag("rootObject");
tag->setFieldValue("intField", 1234);
tag->setFieldValue("longField", 5000000000);
.
BinaryOutput* usds_binary_doc = new BinaryOutput();
clientParser->encode(usds_binary_doc, true, true, true);
const unsigned char* binary_data = usds_binary_doc->getBinary();
size_t binary_size = usds_binary_doc->getSize();
Особенности работы с массивами опущены; вы можете увидеть их отдельно, загрузив пример исходного кода.
Шаг 4. Декодирование двоичного документа:
Для чистоты эксперимента создадим отдельный объект парсера, не будем его инициализировать словарем и посмотрим, будет ли он парсить наш бинарный документ: BasicParser* serverParser = new BasicParser();
serverParser->decode(binary_data, binary_size);
int int_value = 0;
long long long_value = 0;
tag->getFieldValue("intField", &int_value);
std::cout << "\tintField = " << int_value << "\n";
tag->getFieldValue("longField", &long_value);
std::cout << "\tlongField = " << long_value << "\n";
Обратите внимание, что «Сервер» заранее ничего не знает о схеме данных, но спокойно получил бинарник, нашел в нем поля по их текстовым именам и правильно преобразовал их в значения переменных C++.
Эта конкретная функция недоступна в Google Protobuf и ASN.1. Вы можете существенно ускорить работу программы, если инициализировать поля по их числовым идентификаторам (идентификаторам, таким же, как те, что указаны в Словаре), см.
пример исходного кода.
Читабельность для человека Это действительно очень важная особенность: вы не можете читать сторонние бинарные пакеты Google Protobuf или ASN.1 (кроме XER), а иногда очень хочется.
Используя BSON, вы можете конвертировать любой пакет данных в JSON, что уже хорошо.
USDS не отстает: std::string json;
serverParser->getJSON(USDS_UTF8, &json);
std::cout << "JSON:\n" << json << "\n";
Сервер не только получил произвольный двоичный документ, но и смог преобразовать его в JSON. Ту же операцию можно было бы проделать и на стороне «Клиента»: сгенерировать DOM-объект и сразу преобразовать его в JSON, что также строго соответствует схеме данных.
В планы развития USDS входит редактор документов USDS с полноценным графическим интерфейсом.
В ближайшем будущем USDS Basic Parser будет реализовывать преобразование между XML, JSON и USDS в любом направлении.
Заключение Почему я опубликовал сырой продукт (Pre-Alpha), который категорически не рекомендуется использовать в проектах? Мне важен ваш ответ:
- чего не хватает в продукте?
- оно вообще нужно?
- Четко ли написана документация и исходный код?
Источники: Страница проекта: Доллар США 1.0 Вы можете скачать библиотеку и исходный код примера.
Здесь .
Исходный код библиотеки доступен Здесь .
Теги: #xml #json #USDS #программирование
-
Действия По Подключению Двух Компьютеров
19 Oct, 24 -
Древнеперсидский Язык
19 Oct, 24 -
Как Часто Вы Пользуетесь Ноутбуком?
19 Oct, 24 -
Как Данные Передаются По Радио?
19 Oct, 24 -
Мтх: Спешим Поделиться Своими Достижениями
19 Oct, 24