[Из песочницы] Что такое AXON
AXON — это нотация для сериализованного представления объектов, документов и данных в текстовой форме. Она объединяет в себе простоту JSON, расширяемость XML и удобочитаемость YAML.
Есть проект pyaxon на python, с которым можно «поиграться». Впрочем, он создавался таким образом, чтобы не сильно уступать по скорости с модулем json. Поэтому он может сгодиться и для реальных дел.
Зачем AXON?
AXON
появился как попытка справиться с недостатками или неудобствами JSON
и XML
, но сохранить при этом их достоинства и возможности, дополнительно добавив удобочитаемость, присущую YAML
.
AXON содержит «улучшенный» вариант JSON
1. JSON
имеет два неудобства:
- имена атрибутов/ключей, которые являются идентификаторами приходится заключать в кавычки;
- легко забыть запятую в случае вставки новой пары ключ: значение.
AXON
устраняет эти неудобства следующим образом:
- можно не заключать в кавычки имена, которые являются идентификаторами;
- совершенно опускаются разделительные запятые, используются только пробельные символы для разделения элементов.
В результате получается более компактное представление и удобство восприятия при форматировании.
Для сравнения:
JSON
{ "name": "Alex",
"birth": "1979-12-25",
"email": "mail@example.com"}
[ "Alex"
"1979-12-25"
"mail@example.com"]
AXON
{ name: "Alex"
birth: ^1979-12-25
email: "mail@example.com"}
[ "Alex"
^1979-12-25
"mail@example.com"]
2. В JSON
не гарантируется, что после загрузки
{ "name": "Alex",
"birth": "1979-12-25",
"email": "mail@example.com"}
порядок ключей/атрибутов сохранится.
В AXON
констатируется, что
{ name: "Alex"
birth: ^1979-12-25
email: "mail@example.com"}
преобразуется в mapping
без сохранения порядка ключей.
В то же время констатируется, что
[ name: "Alex"
birth: ^1979-12-25
email: "mail@example.com"]
преобразуется в mapping
с сохранением порядка ключей.
3. AXON
поддерживает синтаксиc для представления даты и времени в ISO
-подобном формате:
- даты
^2010-12-31
- времени
^12:30
^12:30:15
^12:30+03:00
^12:30:15-04:30
- даты и времени
^2010-12-31T12:30
^2010-12-31T12:30:05.0125
^2010-12-31T12:30+04:00
^2010-12-31T12:30:05.0123-04:00
а также для представления десятичных чисел:
1D 123456789D
3.14D 1.23e-6D
4. AXON
также позволяет определять метки неатомарных значений и использовать их в качестве внутренних ссылок. Это позволяет при необходимости не создавать копии многократно используемых неатомарных значений при сериализации/десериализации.
Например:
[ { prev: &a (2012-12-30 10:00)
next: &c (2012-01-01 12:00) }
{ prev: &b (2012-12-31 13:00)
next: *a }
{ prev: *c
next: *b } ]
Метка имеет префикс &
(&a &b &c
), а ссылка имеет префикс *
(*a *b *c
).
Модель данных AXON содержит вариант модели Infoset XML в более компактной нотации
Рассмотрим иллюстративный пример XML
представления структурированных данных:
John Smith
25
21 2nd Street
New York
NY
212-555-1234
AXON
реализует идею более простого синтаксиса для представления XML
структурированных данных:
person {
name {"John Smith"}
age {25}
address {
type: "home"
street {"21 2nd Street"}
city {"New York"}
state {"NY"}
}
phone {type:"home" "212-555-1234"}
}
Представление в формате AXON
можно построить из формата XML
за 5 шагов:
- Заменить
наtag {
- Заменить
на
}
- Заменить
attr=value
наattr: value
- Текст внутри элементов заключить в двойные кавычки (
"
) - Удалить символ запятой (
,
) или заменить его на один пробел
Результат такого преобразования структурно идентичен первоначальному XML
документу. По-существу это синтаксически более компактная форма представления XML
документа.
Для сравнения также приведем представление в AXON
с форматированием сложных элементов без {} с использованием принципа одинакового отступа для подэлементов структуры:
person
name {"John Smith"}
age {25}
address
type: "home"
street {"21 2nd Street"}
city {"New York"}
state {"NY"}
phone
type: "home"
"212-555-1234"
Это представление получается из предыдущего удалением всех символов { и }, а также ненужных пустых строк.
AXON расширяет возможности XML и JSON
В XML
атрибуты могут иметь только простые значения, в AXON
значением атрибута может любое значение (как и в JSON
). Кроме того простые значения имеют тип (текст в формате unicode
, число, десятичное число, дата и время, массив байтов в кодировке base64). AXON
можно рассматривать как расширение JSON
в том смысле, что объекты могут именованными, так же как и элементы XML
являются именованными.
Например:
person
name: "John Smith"
age: 25
burn: 1975-10-21
locations: [
address
type: "home"
street: "21 2nd Street"
city: "New York"
state: "NY"
]
contacts: [
phone
type: "home"
"212-555-1234"
email
type: "personal"
"mail@example.com"
]
В JSON
есть одно неудобство, связанное с представлением нерегулярных структур, в которых существенен порядок частей. В таких структурах доступ к элементам осуществляется в результате последовательного поиска по имени, а не в результате «прямого» доступа по имени.
В качестве примера рассмотрим структурированный документ в формате XML
:
paragraph
- item text
paragraph
- item text
paragraph
Непосредственно, без преобразования структуры этот документ не транслируется в JSON
из-за важности порядка и повторяемости элементов. Один вариант трансляции, который эмулирует последовательность именованных элементов имеет вид:
{
"tag": "section",
"@": {"title": "Title"},
"*": [
{ "tag": "par",
"@": {"style":"normal", "text":"paragraph"}},
{ "tag":"enumerate",
"@": {"style": "enumerate"},
"*": [
{ "tag":"item",
"@": {"text":"item text"}}
]
},
{ "tag": "par", "@": {"style":"normal", "text":"paragraph"}},
{ "tag":"itemize",
"*": [
{ "tag":"item", "@": {"text":"item text"}}
]
},
{ "tag": "par", "@": {"style":"normal", "text":"paragraph"}}
]
}
В AXON
такие структуры транслируются «один в один»:
section
title: "Title"
par
style: "normal"
"paragraph"
enumerate
style: "enum"
item { "item text" }
par
style: "normal"
"paragraph"
itemize
style: "itemize"
item { "Item text" }
par
style: "normal"
"paragraph"
AXON поддерживает форматирование в стиле YAML
Привлекательной стороной YAML
является формат представления в стиле wiki
. AXON
также поддерживает подобный стиль форматирования.
Например, для сравнения:
- форматирование без {} (
YAML
-стиль)
person
name: "Alex"
age: 25
- форматирование с {} и отступами (
C/JSON
-стиль)
person {
name: "Alex"
age: 25}
- компактный формат
person{name:"Alex" age:25}
AXON может представлять серию объектов
Одно из ограничений JSON
и XML
связано с тем, что они представляют единственный корневой объект. Напротив, AXON
представляет серию объектов или серию пар ключ
: объект
, которые можно загружать по одному. Например:
- серия объектов
{ name: "Alex"
age: 32 }
{ name: "Michael"
age: 28 }
{ name: "Nick"
age: 19 }
- серия объектов с ключами
alex: {
message: "Hello"
datetime: ^2015-07-12T12:32:35
}
michael: {
message: "How are you"
datetime: ^2015-07-12T12:32:35
}
Комментарии (32)
30 июня 2016 в 20:13
+1↑
↓
Возможно я невнимательно читал, а можно ли запихнуть AXON в AXON?30 июня 2016 в 22:18
0↑
↓
Можно еще добавить пару извращений:
— можно ли запихнуть XML в AXON?
— можно ли запихнуть JSON в AXON?У нас системы общаются на базе AXON и нам нужно прокинуть в еще одну нашу систему XML (или JSON), который получили от пользователя.
30 июня 2016 в 22:57
0↑
↓
Да, можно.
30 июня 2016 в 20:44
0↑
↓
Вопросы
1. Можно-ли без кавычек использовать любой ключ? Например »$3ухлкйл Фр94нк, хи7 3»? Если да, то как это добавит удобочитаемости?
2. Чего именно я достигну используя AXON вместо JSON? Каковы преимущества, кроме представления структур в стиле python-way? Я не заметил в статье ответа на этот вопрос, т.к. описанные неудобства JSON надуманны.30 июня 2016 в 22:21
0↑
↓
Без кавычек можно только идентификаторы.
Необходимость всегда использовать кавычки, как показал мне интернет — не совсем надуманные, впрочем единого мнения тут нет. Что касается запятых, то они, вообще говоря, не обязательны.
Для ответа на второй нужно было бы подробнее описать возможности библиотеки. Но для этого скорее всего получится еще одна статья.
Если кратко, то, например, можно отображать именованные элементы в объекты. Для этого регистрируется функция для его создания.
Пример приведен в ответе дляamaksr
.
30 июня 2016 в 20:56
–1↑
↓
В JSON не гарантируется, что после загрузки
Не верно. В описании json’а лишь говорится:{ «name»: «Alex»,
«birth»:»1979–12–25»,
«email»: «mail@example.com»}порядок ключей/атрибутов сохранится.
An object is an unordered set of name/value pairs.
А порядок при маппинге зависит от библиотеки. В той же java, если мапить объект наLinkedHashMap
, то порядок сохранится.30 июня 2016 в 21:32
0↑
↓
Но, например, в python для представления mapping’s есть два типа: один гарантирует порядок, другой — нет. В JSON, если вы используете библиотеку на языке python, то вы уже не сможете в одних случаях использовать dict, а в других OrderedDict.
30 июня 2016 в 21:04
0↑
↓
Достоинства весьма сомнительные. Интереснее было бы, например, если бы новый формат позволял делать что-то более эффективно. Например экономить память за счет определения структуры объекта один раз для массива объектов. Или чтобы поддерживал разные типы значений, а не только число, сторку и дату. А так получается синтаксис ради синтаксиса.30 июня 2016 в 21:51
0↑
↓
В статье затронут только аспект самой нотации как способа текстового представления объектов.
Разные типы объектов использовать можно. В библиотеке pyaxon есть возможность отображать классы на именованные структурные объекты. Например, можно отобразить
person { name: "Иванов" age: 30 }
на
namedtuple
, определив:text = """ person { name:"Иванов" age:30 } """ Person = namedtuple("Person", "name age") @axon.factory("person") def Person_factory(attrs, vals): return Person(**attrs) vals = axon.loads(text, mode="strict") print(vals[0])
Определение типа для всего списка AXON и библиотека
pyaxon
пока еще не поддерживает.
30 июня 2016 в 21:09
0↑
↓
Документация показывает удобство YAML-like синтаксиса:axon name: "AXON is eXtended Object Notation" atomic_values string: "abc абв 中文本" multiline_string: "one two three" date: ^2012-12-31
первый вопрос на котором себя словил: three» — почему тут есть кавычки? это какая-то специальная пометка?
не сразу заметил, что это конец строки.30 июня 2016 в 21:26 (комментарий был изменён)
0↑
↓
мимо
30 июня 2016 в 22:27 (комментарий был изменён)
0↑
↓
Просто текст, заключенный в кавычки может состоять из нескольких строк.
30 июня 2016 в 22:55
0↑
↓
Да, я понял, но не сразу.
И если на такие грабли можно наступить на столь элементарном примере, то на более сложном это может вылиться в множество потраченных минут / часов на поиск проблемы.Вложите более-менее сложный YAML документ, как многострочное поле в AXON документе, который в свою очередь представлен в виде YAML, это вполне валидный кейс:
— вы записываете в файл данные, пришедшие извне, в формате AXON в представлении YAML, для удобства чтения.Шутки про вложение XML в JSON (или даже JSON в JSON) смешные, пока не столкнешься с ними в реальном проекте.
30 июня 2016 в 23:04 (комментарий был изменён)
0↑
↓
Ну может получиться нечто вроде этого:
.............. config: " option1: \"asdasdsadsd\" option2: \"erwrwetrter\" option3: \"vcnbnbmv\" " ............
Для этих целей преудсмотрена альтернатива:
.............. config: ` option1: "asdasdsadsd" option2: "erwrwetrter" option3: "vcnbnbmv" ` ............
Символ ` конечно нелегко заметить, может имеет смысл заменить его ```.
30 июня 2016 в 21:17
+3↑
↓
имена атрибутов/ключей, которые являются идентификаторами приходится заключать в кавычки;
легко забыть запятую в случае вставки новой пары ключ: значение.Это вы оригинальничаете или просто не в теме? Вторым пунктом ВСЕГДА идет отсутствие комментариев и не надо ничего придумывать. Запятую они могут забыть… Надо изучать матчасть перед началом разработки:
JSON, который можно комментировать
KTV. Новый JSON
JSON для любителей скобочек
Усложнённый упрощённый JSON
Universal Binary JSON — ещё один бинарный JSON
jsonex — упрощаем сложные клиент-серверные диалоги
JSON с комментариями (github, внизу смотреть список аналогичных проектов)
Tree — убийца JSON, XML, YAML и иже с ними — однозначно рекомендую комменты к прочтению30 июня 2016 в 22:01
0↑
↓
Комментарии в AXON имеются в стиле python.
Претензию на оригинальность можно было бы принять, если бы AXON претендовал на оригинальность. Это эксперимент, возможно удачный, возможно не очень.
30 июня 2016 в 23:28
+1↑
↓
Надо бы подумать, прочитать все это на эту тему и разработать JSON 2.0 — с комментариями, с возможностью не ставить кавычки для простых типов (числа, идентификаторы) и возможно чего-то еще. Но именно JSON, а не новый формат.
Что касается YAML’а, то мне как-то не нравятся пробело-табо-зависимые форматы. С другой стороны, yaml уже есть, зачем пытаться совместить все сразу?30 июня 2016 в 23:55
0↑
↓
В первоначальной версии форматирования в стиле YAML отсутствовало. Оно было добавлено как возможность.
Принципиальное отличие от JSON в том, что AXON имеет именованные элементы.Что касается JSON 2.0, то он принципиально привязан в синтаксису javascript. И скорее всего, придется ждать пока все перечисленное не появится в формате JSON как части javascript.
30 июня 2016 в 21:24
0↑
↓
JSON имеет два неудобства:
- имена атрибутов/ключей, которые являются идентификаторами приходится заключать в кавычки;
- легко забыть запятую в случае вставки новой пары ключ: значение.
AXON устраняет эти неудобства следующим образом:- можно не заключать в кавычки имена, которые являются идентификаторами;
- совершенно опускаются разделительные запятые, используются только пробельные символы для разделения элементов.
JSON имеет куда более неприятные особенности, чем приведенные в статье.
Как вариант, в JSON необходимо каждый раз указывать все имена полей в массиве однотипных объектов. Из-за этого объем json документа существенно увеличивается.Убрать кавычки, если ключ имеет вид идентификатора — это существенное усложнение парсера, которое позволит сэкономить 20 символов для строки длинной в 300 символов.
К тому же из документации не понятно, можно ли кавычку » или какой-то спец.символ использовать как Ключ, как вариант для конфигурации автозамены.
30 июня 2016 в 21:27
0↑
↓
Как вариант, в JSON необходимо каждый раз указывать все имена полей в массиве однотипных объектов
Зачем?30 июня 2016 в 21:33 (комментарий был изменён)
0↑
↓
Предположим у нас массив оценок за тест:[{"name": "A", "score": 90}, {"name": "B", "score": 80}, {"name": "C", "score": 70}, {"name": "D", "score": 60}]
Можно обойти, задав жесткий контракт:
[["A", 90], ["B", 80], ["C", 70], ["D", 60]]
Но семантика уже не та.
30 июня 2016 в 21:37
0↑
↓
Но семантика уже не та
А как на счет:{ "type": ["name", "scope"], "collection": [["A", 90], ["B", 80], ["C", 70], ["D", 60]] }
30 июня 2016 в 21:52
0↑
↓
Этот вариант намного лучше!Но теперь нужно писать encoder / decoder для этого формата во всех частях системы на всех языках, которые в нашей системе будут и нам очень повезет, если у нас будет язык со слабой типизацией.
Но это уже трейдоф: решили проблему объема данных, заплатили написанием кастомного парсера.30 июня 2016 в 22:52 (комментарий был изменён)
0↑
↓
А можно так:
data { type: ("name" "scope") ("A" 90) ("B" 80) ("C" 70) ("D" 60) }
@axon.factory("data") def data_factory(attrs, vals): name, scope = attrs["type"] tp = get_type_factory(name, scope) return [tp(args) for args in vals]
30 июня 2016 в 23:29
0↑
↓
Это ни чем не лучше приведенного выше примера JSON. Недостатки те же.Кстати, семантически ваш пример, это Node, Dict, Set или что?
1 июля 2016 в 00:02
0↑
↓
Согласен, что не лучше. Но использование именованного элемента дает идиоматический способ преобразования в объектное представление при наличии зарегистрированных порождающих функций.
Без отображения — это Node. С отображением — список объектов типа, который вернет get_type_factory.
30 июня 2016 в 22:40
0↑
↓
Строка из одной кавычки будет записана как »\»
Для массива из однотипных объектов можно было бы предложить, например, такое решение:
persons { {name: "Иванов" age: 30} {name: "Сидоров" age:33} }
@axon.factory("persons") def persons_factory(attrs, vals): return [Person(**val) for val in vals] vals = axon.loads(text, mode="strict") print(vals)
В результате получим
[[Person(name='Иванов', age=30), Person(name='Сидоров', age=33)]]
30 июня 2016 в 21:27
0↑
↓
В JSON не гарантируется, что после загрузки
{ «name»: «Alex»,
«birth»:»1979–12–25»,
«email»: «mail@example.com»}порядок ключей/атрибутов сохранится.
В AXON констатируется, что
[ name: «Alex»
birth: ^1979–12–25
email: «mail@example.com»]преобразуется в mapping с сохранением порядка ключей.
В JSON тоже можно массивы.
30 июня 2016 в 21:54
0↑
↓
[ name: "Alex" birth: ^1979-12-25 email: "mail@example.com"]
это не массив
30 июня 2016 в 22:09 (комментарий был изменён)
0↑
↓
В AXON — да, это не массив, но проблему порядка ключей и значений в JSON можно решить через массив:[ ["name", "Alex"], ["birth", "1979-12-25"], ["email", "mail@example.com"] ]
или:[ {"name": "Alex"}, {"birth": "1979-12-25"}, {"email": "mail@example.com"} ]
в зависимости от предпочтений, технических возможностей и ограничений.При этом использовать стандарт разметки, которы поддерживается во всех языках и давно отлажен и отлично работает.
30 июня 2016 в 22:44
0↑
↓
Да можно, но при этом усложнится обработка такого массива.
В данном случае просто есть встроенная возможность получить словарь (ordered dict).
30 июня 2016 в 23:46
0↑
↓
Смею не согласиться. Такой функционал крайне редко нужен (далеко не в каждом языке есть ordered dict). Но если он потребуется, то дополнительные 5–10 строк кода для обертки над таким массивом будет с головою достаточно.