YSON
В данном разделе собрана информация про YSON — JSON-подобный формат данных.
К основным отличиям YSON от JSON относится:
- Поддержка бинарного представления скалярных типов (чисел, строк и булевого типа);
- Атрибуты: произвольный словарь, который можно установить дополнительно на литерал любого — даже скалярного — типа.
Кроме того, существуют синтаксические отличия:
- Вместо запятой в качестве разделителя используется точка с запятой;
- В словарях ключ от значения отделяется не двоеточием, а знаком равенства:
=; - Строковые литералы не обязательно всегда заключать в кавычки — только если возникает неоднозначность при парсинге;
Имеется следующий набор скалярных типов:
- Строки (
string); - Знаковые и беззнаковые 64-битные целые числа (
int64иuint64); - Числа с плавающей точкой двойной точности (
double); - Булев (логический) тип (
boolean); - Специальный тип entity, имеющий всего один литерал (
#).
Скалярные типы обычно имеют как текстовое, так и бинарное представление.
Есть два композитных типа:
Скалярные типы
Строки
Токены строк бывают трёх видов:
-
Идентификаторы задаются регулярным выражением
[A-Za-z_][A-Za-z0-9_.\-]*, расширенные C-идентификаторы, отличие в символах-,.. Идентификатор задает строку с идентичным ему содержимым и используется в первую очередь для краткости (не нужно ставить кавычки).Примеры:
abc123;_;a-b.
-
Текстовые строки — C-escaped строки в двойных кавычках.
Примеры
"abc123";"";"quotation-mark: \", backslash: \\, tab: \t, unicode: \xEA".
-
Бинарные строки:
\x01 + length (protobuf sint32 wire format) + data (<length> bytes).
Знаковые 64-битные целые числа (int64)
Два способа записи:
- Текстовый (
0,123,-123,+123); - Бинарный:
\x02 + value (protobuf sint64 wire format).
Беззнаковые 64-битные целые числа (uint64)
Два способа записи:
- Текстовый (
10000000000000,123u); - Бинарный:
\x06 + value (protobuf uint64 wire format).
Числа с плавающей точкой (double)
Два способа записи:
- Текстовый:
0.0,-1.0,1e-9,1.5E+9,32E1; - Бинарный:
\x03 + protobuf double wire format.
Внимание
Текстовое представление чисел с плавающей точкой включает в себя округление, которое может привести к тому, что при обратном парсинге значение окажется иным. В случае, если вам важна точность, следует использовать бинарное представление.
Булевы литералы (boolean)
Два способа записи:
- Текстовый (
%false,%true); - Бинарный (
\x04,\x05).
Entity (entity)
Entity представляет собой атомарное скалярное значение, не имеющее собственного содержимого. Сценарии, в которых данный тип может быть полезен, разнообразны. Например, часто entity обозначает null. Также при запросе get на поддерево Кипариса файлы и таблицы возвращаются в виде entities (полезные данные при этом хранятся в атрибутах данного узла).
Лексически entity кодируется символом диеза: #.
Выделенные литералы
Специальные токены:
;, =, #, [, ], {, }, <, >, ), /, @, !, +, ^, :, ,, ~.
Не все эти символы используются в YSON, некоторые используются в YPath.
Композитные типы
Список (list)
Задаётся следующим образом: [value; ...; value], где value — литералы произвольных скалярных или композитных типов.
Пример: [1; "hello"; {a=1; b=2}].
Словарь (map)
Задаётся следующим образом: {key = value; ...; key = value}. Здесь *key* — литералы строкового типа, а value — литералы произвольных скалярных или композитных типов.
Пример: {a = "hello"; "38 parrots" = [38]}.
Атрибуты
На любой литерал в YSON можно установить атрибуты. Формат записи: <key = value; ...; key = value> value. Внутри угловых скобок синтаксис аналогичен словарю. Например, <a = 10; b = [7,7,8]>"some-string" или <"44" = 44>44. Но чаще всего атрибуты можно встретить на литералах типа entity, например, <id="aaad6921-b5704588-17990259-7b88bad3">#.
Грамматика
YSON-данные бывают трех типов:
- Node (одно дерево, в примере —
<tree>) - ListFragment (значения, разделенные
;, в примере —<list-fragment>) - MapFragment (пары ключ-значение, разделенные
;, в примере —<map-fragment>)
Грамматика (определяется с точностью до пробельных символов, которые могут быть в произвольном количестве добавлены и удалены между токенами):
<tree> = [ <attributes> ], <object>;
<object> = <scalar> | <map> | <list> | <entity>;
<scalar> = <string> | <int64> | <uint64> | <double> | <boolean>;
<list> = "[", <list-fragment>, "]";
<map> = "{", <map-fragment>, "}";
<entity> = "#";
<attributes> = "<", <map-fragment>, ">";
<list-fragment> = { <list-item>, ";" }, [ <list-item> ];
<list-item> = <tree>;
<map-fragment> = { <key-value-pair>, ";" }, [ <key-value-pair> ];
<key-value-pair> = <string>, "=", <tree>; % Key cannot be empty
Символ ; после последнего элемента внутри <list-fragment> и <map-fragment> может быть опущен. Следующие конструкции следует считать валидными при чтении:
|
C |
Сокращенная запись |
|
|
Примеры
-
Map (Node)
{ performance = 1 ; precision = 0.78 ; recall = 0.21 } -
Map (Node)
{ cv-precision = [ 0.85 ; 0.24 ; 0.71 ; 0.70 ] } -
List (Node)
[ 1; 2; 3; 4; 5 ] -
String (Node)
foobar"hello world" -
Int64 (Node)
42 -
Double (Node)
3.1415926 -
ListFragment
{ key = a; value = 0 }; { key = b; value = 1 }; { key = c; value = 2; unknown_value = [] } -
MapFragment
do = create; type = table; scheme = {} -
HomeDirectory (Node)
{ home = { sandello = { mytable = <type = table> # ; anothertable = <type = table> # } ; monster = { } } }
Работа с YSON из кода
Обычно пользователям не приходится работать напрямую с YSON. При использовании одного из официальных YTsaurus-клиентов YSON-структуры будут выражаться в одном из перечисленных ниже видов:
- C++:
TNode— класс, обеспечивающий динамическое DOM-подобное представление YSON-документа; - Python:
YsonType— YSON-типы мимикрируют под Python типы. YSON-атрибуты объектаxможно получить так:x.attributes, это Python словарь; - Java:
YTreeNode— интерфейс, обеспечивающий динамическое DOM-подобное представление YSON-документа.