Tree — убийца JSON, XML, YAML и иже с ними

Здравствуйте, меня зовут Дмитрий Карловский и я… много думал. Думал я о том, что не так с XML и почему его в последнее время променяли, на бестолковый JSON. Результатом этих измышлений стал новый стандарт формат данных, который вобрал в себя гибкость XML, простоту JSON и наглядность YAML.

image Tree — двумерный бинарно-безопасный формат представления структурированных данных. Легко читаемый как человеком так и компьютером. Простой, компактный, быстрый, выразительный и расширяемый. Сравнивая его с другими популярными форматами, можно составить следующую сравнительную таблицу:
Больше — лучше JSON XML YAML INI Tree
Человекопонятность 3 1 4 5 5
Удобство редактирования 3 1 4 5 5
Произвольная иерархия 3 3 3 1 5
Простота реализации 3 2 1 5 5
Скорость парсинга/сериализации 3 1 1 5 5
Размер в сериализованном виде 3 1 4 5 5
Поддержка поточной обработки 0 0 5 5 5
Бинарная безопасность 3 0 0 0 5
Распространённость 5 5 3 3 0
Поддержка редакторами 5 5 3 5 1
Поддержка языками программирования 5 5 3 5 1

Сравнение форматов


Человекопонятность

JSON и XML позволяют произвольно форматировать вывод пробелами и переносами строк. Однако, часто по различным причинам (основные — меньший объём, проще реализация) их форматируют в одну строку и тогда они становятся крайне не читаемыми.

{ "users" : [ { "name" : "Alice" , age : 20 } ] }

<users><user><name>Alice</name><age>20</age></user></users>

Кроме того, JSON не поддерживает многострочные тексты — они всегда представляются в виде одной строки, со специальной escape-последовательностью вместо переводов строк.

{ "description" : "Hello, Alice!\nHow do you do?" }

С другой стороны, XML позволяет внедрять свои тэги внутрь текста, что наглядно для простой разметки типа «выделение жирным», но сложная разметка типа «гиперссылка» даёт резко противоположный эффект.

<greeting>
    Hello, <b>Alice</b>!<br/>
    How do you do?
</greeting>

<greeting>
    Hello, <a href="http://example.org/user/alice?ref=xe3o7rubvo283xb">Alice</a>!<br/>
    How do you do?
</greeting>

Если текст содержит «специальные символы», то их приходится экранировать escape-последовательностями. В XML эти последовательности особенно громоздки и ненаглядны. А вот в Tree, наоборот, экранирование не требуется вовсе.

<title>"Rock&roll" = life</title>

{ "title" : "\"Rock&roll\" = life" }

image

Удобство редактирования

JSON и XML довольно неудобно редактировать без специальных редакторов, понимающих их синтаксис. Как минимум необходима разноцветная подсветка лексем. Очень помогает — автоформатирование, автодополнение и подсветка ошибок. К сожалению, экранировать спецсимволы приходится вручную во всех форматах, кроме Tree, где оно не требуется.

Произвольная иерархия

INI имеет жёстко ограниченную глубину иерархии.

В XML произвольные дочерние узлы могут быть только у элементов — это вынуждает использовать их вместо, например, аттрибутов, для большей гибкости и единообразия.

JSON и YAML для создания иерархий предлагают «списки» и «мапки». Не все структуры данных хорошо представимы с их помощью. Например, различные AST, где имена узлов могут повторяться и порядок следования которых важен.

В Tree есть только один тип узлов и любой узел может содержать произвольные дочерние. Как следствие, он не накладывает никаких ограничений на иерархию.

Простота реализации

JSON

Довольно простая грамматика (30 паттернов), чем и обусловлено большое число реализаций под разные языки.

XML

Довольно сложная грамматика (90 паттернов), которая могла бы быть куда проще, если бы не требование совместимости с sgml.

YAML

Крайне сложная грамматика (210 паттернов). Нужно быть очень терпеливым человеком, чтобы реализовать все нюансы, и потратить много человекочасов, чтобы избавиться ото всех багов.

INI

Крайне простая грамматика (8 паттернов), позволяющая описывать лишь одну, довольно простую структуру (ключ-ключ-значение).

Tree

Очень простая грамматика (10 паттернов), что, однако, не мешает описывать с его помощью произвольные иерархические структуры.

Скорость парсинга/сериализации

Не вдаваясь в сравнение скорости работы конкретных имплементаций, оценим теоретические пределы скоростей работы с разными формтами.

Предельная скорость обработки данных зависит от сложности синтаксиса. Именно поэтому YAML парсится на порядок дольше, чем JSON, а XML по скорости где-то между ними.

Tree помимо простой грамматики имеет ещё одно существенное преимущество — отсутствие необходимости в экранировании и разэкранировании спецсимволов.

Размер в сериализованном виде

Примеры файлов на разных языках: github.com/nin-jin/tree.d/tree/master/formats

Как видно, существенно больше всех места занимает XML, даже если его минифицировать. JSON в читабельном виде и YAML где-то по середине. А самые компактные — INI, Tree и минифицированный в одну строку JSON.

Поддержка поточной обработки

Поддерживающие поточную обработку форматы, позволяют добавлять данные в файл, просто подклеивая их в конец. Яркий пример — различные логи. И наоборот — нормально распарсить данные, имея лишь некоторое число начальных строк.

В случае XML и JSON такой возможности нет — документ с обрезанным концом или дополнительными данными в конце, является невалидным.

Бинарная безопасность

Почти все текстовые форматы не совместимы с бинарными данными. Именно поэтому Tree — на самом деле не текстовый формат, хотя его и можно редактировать в текстовом редакторе при соблюдении некоторых ограничений (использовать только unix-переводы строк, табуляцию для отступов, и не использовать произвольные бинарные данные).

Распространённость

XML довольно продолжительное время был в тренде, так что нашёл применение во множестве мест. Сейчас уверенными темпами популярность набирает JSON, благодаря своей простоте, но ценой некоторой потери гибкости. INI за счёт своей ограниченности применялся лишь для различных конфигов, но сейчас замещается более гибкими форматами. YAML остаётся довольно нишевым форматом ввиду своей переусложнённости, хотя и снискал некоторую популярность у любителей «писать меньше, делать больше, а потом хоть трава не расти». Tree пока ещё вначале пути и надеюсь не в конце.

Поддержка редакторами

XML и JSON благодаря своей популярности поддерживаются везде. Над поддержкой YAML многие разработчики редакторов просто не видят целесообразности заморачиваться. INI настолько прост, что для него никакой особой поддержки и не нужно. С Tree в принципе та же картина, но есть один плагин к IDEA о котором будет рассказано далее.

Поддержка языками программирования

Тут в целом та же ситуация, что и с поддержкой редакторами. Разве что для Tree есть две реализации — на языках D и TypeScript/JavaScript.

Подробнее о Tree


Уровни представления

Уровень формата. Определяет базовую модель данных и представление её в сериализованном виде.
Уровень языка. Определяет семантику узлов и представление их в отличных от Tree форматах.
Уровень приложения. Определяет API для взаимодействия с моделью данных Tree.

Модель данных

Модель Tree крайне проста — есть только один тип узлов, и каждый узел имеет: имя, значение, список дочерних узлов. Имя и значение являются взаимоисключающими, так что условно все узлы можно разделить на 3 типа:
Имена — узлы с непустым именем и пустым значением. Используются для именования поддеревьев. В имени не может быть пробельных символов, символа перевода строки и символа равенства.
Значения — узлы с пустым именем. Используются для хранения значений. Единственное ограничение на значения — они не могут содержать символ перевода строки.
Коллекции — узлы с пустым именем и значением, но не пустым списком дочерних узлов. Используются для работы со списком узлов как с одним узлом. В результате парсинга возвращается именно коллекция, содержащая список корневых узлов.

В Tree нет комментариев или инструкций процессору, знакомых нам из XML. Нет списков или мапок из JSON и YAML. Нет специального синтаксиса для секций, как в INI. Однако они и не только они могут быть введены в языках, основанных на формате Tree.

Строковое представление

Tree-файл состоит из набора строк, разделённых символом перевода строки (0x0D). Каждая строка начинается с некоторого количества символов табуляции, показывающих какой из предков является родителем первого узла в строке. И далее идёт список узлов разделённых пробелами. Каждый следующий при парсинге вкладывается в предыдущий. Узлы-имена представляются просто своим именем. Узлы-значения – значением, предварёнными символом равенства.
В одной строке может быть произвольное число узлов-имён, но узел-значение может быть только один, причём самым последним. Значение может содержать абсолютно любые символы за исключением символа перевода строки. Когда нужно поместить произвольные бинарные данные – их предварительно надо разбить по символу перевода строки на несколько узлов-значений. А при приведении дерева к строке именованные узлы будут отброшены, а данные из узлов-значений будут выведены как есть и между ними будут вставлены переводы строк.
Наличие табуляции в строке означает, что первый узел в этой строке должен быть вложен в последний узел последней строки имеющей табуляцию на один меньше.

По сухому описанию довольно сложно ухватить суть, так, что далее будет множество наглядных иллюстраций…

Примеры применения Tree в разных областях


Контекстно свободные грамматики

Хоть формат Tree и не является контекстно свободным, но разбить на лексемы его можно по сравнительно не сложной контекстно свободной грамматике, которую можно выразить тоже в формате Tree:

image

Подробнее о языке grammar.tree
Описание грамматики состоит из списка слов, для каждого из которых внутри задан соответствующий ему шаблон.

is

Предикат эквивалентности. Обозначает, что родительский узел может быть заменён на последовательность дочерних шаблонов.

image

Данное выражение определяет STATEMENT как последовательность из некоторого «выражения», за которым следует символ «точка с запятой».

octet

Совпадает с одним октетом (8 бит) с указанным внутри шестнадцатиричным значением.

image

Тут мы определяем SEMICOLON как октет с заданным значением. Если значение опущено, то такой шаблон совпадает с любым значением.

optional

Допускает отсутствие дочернего шаблона.

image

Совпадает либо с двумя байтами: возвращения каретки после которого идёт перевода строки. Либо с одним переводом строки.

any-of

Сопоставится с одним и только одним из дочерних шаблонов.

image

list-of

Позволяет последовательно повторить дочерний шаблон произвольное число раз (но как минимум одно совпадение должно быть).

image

Тут DELIMITER совпадёт с не пустой последовательной группой пробелов.

except

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

image

Тут мы определяем EXPRESSION как произвольное число байт ни один из которых не является «точкой с запятой».

image

А этот шаблон уже совпадёт с произвольным набором байт (в том числе содержащего «точку с запятой»), но только не с одиночной «точкой с запятой».

with-delimiter

Указывает, что совпадения сестринских шаблонов должны быть разделены дочерним шаблоном.

image

Здесь SCRIPT определён как набор выражений, разделённых заданным символом.

Лог доступа к веб-серверу

Расширяемый структурированный формат логов. Может показаться громоздким, зато очень быстро и точно парсится как человеком так и машиной.

image

Поток сообщений от сервера в чате

Специальный разделитель "---" говорит клиенту о том, что завершилась пересылка очередной порции данных и можно приступать к её обработке.

image

Вёрстка статической веб-страницы

Специальный DSL на базе Tree позволяет лаконично описывать XML любой сложности. Трансформер из xml.tree в xml понимает специальные узлы «@», «!» и «?» формируя атрибуты, комментарии и инструкции процессору.

image

Подробнее о языке xml.tree
Структурные узлы соответствующие QName – элементы. Узлы данных – текстовые узлы.

image

     <html>
        <head>
            <title>Рога & Копыта</title>
        </head>
        <body>
            <h1>Привет!</h1>
            <p>Хочешь, я расскажу тебе сказку?</p>
        </body>
    </html>

Атрибуты представляются как узлы с QName именем, помещённые в узлы с именем «@».

image

    <script type="text/javascript" src="index.js" />

Имена атрибутов повторяться не должны. Значением атрибута является текст, но также внутри может быть и дерево, которое при создании XML должно быть сериализовано в текст.

Вложенные основанные на формате Tree языки помещаются в узел с именем этого языка, который помещается в узел c именем «%». От процессора требуется поддержка используемых языков, иначе он не сможет правильно собрать XML. Вложенные языки сериализуются в строку по своим правилам и вставляются в XML в качестве текстового узла.

image

    <link
        rel="canonical"
        href="/?article=rock%26roll&author=Nin+Jin"
    />

Комментарии помещаются в узел с именем "--". Заметьте, что в комментарий помещается всё поддерево, которое сериализуется по всем правилам xml.tree.

image

    <!--<a href="/">top</a>-->

Инструкции процессору помещаются в узлы с именем "?" и могут содержать как просто какие-то значения, так и пары ключ-значение.

image

    <?xml version="1.0" stanalone="yes" ololo?>

Дамп реляционной базы данных

Заметьте, тут используется приём расширения языка. Сначала мы декларируем схему базы данных, а потом используем заданные в схеме имена в качестве DSL для описания данных.

image

Абстрактное Синтаксическое Дерево

Эта структура данных используется языковыми трансляторами в качестве внутреннего представления обрабатываемых ими языков. Программируя на NodeJS велик соблазн использовать в качестве AST — некоторое подмножество JSON.

Например, у нас есть следующий исходник на JS:

function getEl( id ){
	return document.getElementById( id )
}

Интуитивно кажется, что AST должен выглядеть как-то так:

[
	{ "function": {
		"name": "getEl",
		"args": [ "id" ],
		"body": [
			{ "return": [
				{ "get": "document" },
				{ "call": {
					"name": "getElementById",
					"args": [
					 	{ "get": "id" }
					]
				}}
			]}
		]
	}}
]

Однако, это довольно не удобный для работы формат, так как чтобы узнать тип узла нужно проитерироваться по его свойствам и взять имя первого собственного свойства. Поэтому, чаще можно встретить формат типа такого, где первый элемент списка содержит тип узла, остальные — различный набор параметров специфичный для этого типа:

[ [ "function",
    "getEl",
    [ "id" ],
    [ "return",
      [ [ "get",
          "document" ],
        [ "call",
          "getElementById",
          [ "get", "id" ]
        ]
      ]
    ]
  ]
]

А теперь сравните с реализацией в Tree формате:

image

Редактирование других форматов, через Tree представление

Основная фишка модели данных Tree заключается в том, что она позволяет описывать почти любые другие модели данных. Например, модель данных XML — это сильно усечённая модель данных Tree.

Что это значит? А значит это, что многие форматы могут быть транслированы в некоторое подмножество Tree и обратно без потерь. То есть, вместо того, чтобы редактировать, например, XML как он есть, редактор может налету преобразовать его в xml.tree язык, позволив пользователю редактировать его в более удобной и наглядной форме, а при сохранении, делать обратное преобразование и сохранять именно XML.

Структурированный UNIX-трубопровод

Суть проблематики и вариант решения с использованием JSON можно почерпнуть из статьи "JSON pipes в шелле". Вкратце: в linux все команды выводят результат в неструктурированном ориентированном на человека виде, что затрудняет компоновку их друг с другом. Там предлагается использовать JSON, который привносит структуру, но ухудшает читаемость и производительность. Формат Tree в этом случае может привнести структуру практически не теряя ни в читаемости, ни в производительности.

Язык декларативного программирования

Формат Tree мог бы решить основную проблему языка Lisp — неимоверное число скобочек. Если в Lisp всё описывается как списки, то в языке на основе Tree — всё есть деревья. Точно также программа представляла бы из себя некий AST, который мог бы модифицировать сам себя для создания DSL на все случаи жизни, достигая максимальной выразительности.

Эталонная реализация


На языке D парсинг занимает не более 50 строк, а сериализация — 20. Простейший язык запросов — 15. Итого, чуть более 100 строк занимает минимально необходимый функционал: github.com/nin-jin/tree.d

Парсинг:
    string data = cast(string) read( "path/to/file.tree" ); // read from file
    Tree tree = Tree.parse( data , "http://example.org/source/uri" ); // parse to tree

Глубокие запросы:
    Tree userNames = tree.select( "user name" ); // returns name-nodes
    Tree userNamesValues = tree.select( "user name " ); // returns value-nodes

Работа с узлами:
    string name = userNames[0].name; // get node name
    string stringValue = userNames[0].value; // get value as string with "\n" as delimiter
    uint intValue =  userNames[0].value!uint; // get value converted from string to another type

    Tree[] childs = tree.childs; // get child nodes array
    string uri = tree.uri; // get uri like "http://example.org/source/uri#3:2"

Сериализация:
    string data = tree.toString(); // returns string representation of tree
    tree.pipe( stdout ); // prints tree to output buffer

Поддержка редакторами


В данный момент есть лишь плагин подсветки синтаксиса Tree к IDEA, но он понимает только базовые конструкции формата, описанные выше. Для языков на базе Tree нужно будет сделать отдельные плагины или же один, но расширяемый с помощью схем.

Кроме того, Alex222 буквально за вечер написал плагин к SynWrite

Заключение


Надеюсь мне удалось заразить вас идеей использования замечательного формата Tree. Рассказывайте о нём другим. Пишите библиотеки на используемых вами языках. Внедряйте хотя бы опциональную его поддержку в ваши приложения. Ищите ему новые применения — уверен их ещё много. И тогда у него будет шанс на выживание в современном мире Трендо Ориентированного Программирования.

Обновление от 2016-09-11



Так как символ равенства многих вводил в заблуждение касательно своего предназначения (он не является разделителем ключа и значения, а является маркером начала сырых данных), то в реализациях он уже заменён на обратную косую черту.

Например:
! City : table
	ID : field
		type : int 11
		null : false
		unique : true
	Name : field
		type : char 35
		null : true
		unique : false
City
	ID : 1
	Name : \Kabul
City
	ID : 4079
	Name : \Rafah
City
	ID : 23023
	Name : \Moscow


Тут в качестве разделителя ключа и значения используется узел с именем ":", а сырые данные предваряются "\".
Поделиться публикацией
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама
Комментарии 629
  • +39
    Сделайте возможным пробел в качестве первого символа значения, иначе у вас ничего не получится.
    • –12
      Имеете ввиду сделать префикс значения не "=" а "= "?

      Изначально так и было. И отступы пробелами можно было делать. И переводы строк хоть юниксовые, хоть виндовые. Но что даёт нам этот разброд и шатание? Только усложнение всех систем, которые должны это всё поддерживать. Вот в XML вообще пишут слитно имя атрибута и значение, и никто не возмущается.

      У предлагаемого вами разделителя я вижу следующие проблемы:
      1. Не очевидно, что пробел не входит в значение и вообще не очень понятно с первого взгляда в какой момент оно начинается.
      2. Легко не заметить, что поставил 2 пробела вместо 1
      3. Нужно решать, что делать с ситуацией, когда после символа равенства идёт не пробел.
      4. +1 бесполезный (не несущий дополнительной семантики, только оформительский) байт на каждое значение.
      • +29
        > Вот в XML вообще пишут слитно имя атрибута и значение, и никто не возмущается.
        Там атрибуты — самый мелкий уровень, важнее отличить их друг от друга, чем имя от значения. Тут ситуация другая.

        Большинство проблем надуманные.
        1. Можно так же сказать, что неочевидно, входит ли знак равно в значение, или пробел до знака равно в название ключа.
        2. С моноширинным шрифтом сложно. А вот легко, например, не заметить проблемы вместо табуляции, однако вас это не смущает.
        3. Ничего страшного в отсутствии пробела нет.
        4. Без него «человекопонятность» никак не тянет на пятерочку.
        • –18
          Не вижу никакой разницы. Имена и значения в Tree — это практически и есть атрибуты XML.

          1. Можно, но куда сложнее.
          2. Не сложно, некоторые даже могут начать пытаться выравнивать значения пробелами после символа равенства, как они привыкли делать, например, в JSON. Про пробелы ругнётся либо редактор, когда попытается подсветить синтаксис, либо парсер, когда попытается распарсить.
          3. Страшно — когда что-то может быть, а может не быть. Чем чётче синтаксис, тем проще с ним работать.
          4. YAML как раз и получился в погоне за «человекопонятностью», а точнее за гламурным отображением. Понятность должна быть не только для человека, но и для машины. При этом машина должна чётко понимать, что имел ввиду человек, а человек должен чётко понимать, как это поймёт машина. Лишний пробел, который кажется вам критически важным, в лучшем случае никак не повлияет на точность понимания ни человеком, ни машиной. А в худшем — внесёт дополнительную неопределённость.
          • +16
            Для меня, как для программиста, ратующего за аккуратность кода, конструкция типа

            value =2

            просто недопустима. Это выглядит ужасно и неаккуратно. Лучше уж «value=2», чем ЭТО.
            • –14
              А для максимальной аккуратности стоит писать так:
              Value is equal 2.
              

              , забросить инженерное дело и заняться дизайном.
              • +4
                Не стоит так бросаться на всех, своё же детище так закопаете. В лучшем случае появятся более успешные форки.
                Мне лично тоже правильнее смотрятся:
                user
                	name=vintage
                	age=30
                

                и
                user
                	name = vintage
                	age = 30
                

                Просто потому что приятная симметрия. Второй вариант ещё читается лучше.

                Если формат весь из себя такой гибкий, то можно было бы менять поведение парсера через первую строку в файле, а поведение по умолчанию выбрать голосованием.
                • –8
                  Чтобы понять, почему именно так, попробуйте представить, что вместо символа "=" используется символ, например, "|". Единственная его функция — не разделять ключ и значение (это хоть и частый, но всего-лишь частный случай), а именно показывать начало потока бинарных данных.

                  Формат прежде всего простой, потом уже гибкий, а потом уже читабельный и в последнюю очередь компактный. Ни в одной из этих ипостасей он не идеален и при желании (а его я смотрю у хабраюзеров хоть отбавляй) всегда можно найти к чему придраться. Но всё же, на мой взгляд, он представляет из себя неплохой компромис в отличие от остальных упомянутых тут форматов, которые в чём-то хороши, а в чём-то просто отвратительны.
                  • +2
                    Формат прежде всего простой, потом уже гибкий, а потом уже читабельный и в последнюю очередь компактный
                    Никого не волнует насколько формат прост в реализации, его пишут 1 раз, обычно вообще есть несколько либ которые все используют, и всем до лампочки насколько формат прост. Формат должен быть в первую очередь читабельным/удобным для редактирования и потом — гибким.
                    • –1
                      У каждого, работающего с форматом, человека, в голове есть свой маленький криво написанный интерпретатор.
                      • +1
                        Совершенно верно, но кривизна этого интерпретатора сильно зависит от количества неочевидных моментов в формате. Так вот, в вашем формате такой неочевидный момент в каждом знаке равенства.
                        • –2
                          От количества правил. Степень очевидности — дело привычки.
                          • 0
                            Очевидность надо измерять для человека, впервые этот формат увидевшего. А то некоторые и Qr-коды читают, так что, они от этого стали человекопонятными и очевидными?
                            • 0
                              Эскейп последовательности, конечно, куда очевидней, для впервые их увидевшего, да.
                              • 0
                                В тех же XML и JSON надо экранировать далеко не каждую строку.
                                А вот в вашем Tree непонятность с пробелом и знаком равенства — в каждой строке, содержащей узел-значение.
                                • –1
                                  Какая непонятность? После знака равенства и до конца строки — значение.
                                  • 0
                                    Очевидность надо измерять для человека, впервые этот формат увидевшего.
                    • 0
                      А чем пробел и знак равенства проще чем просто знак равенства перед значением?

                      И как реализовать многострочное значение без \n? Только начиная каждую строку со знака пробела и равенства? Не выход.
                      • 0
                        Пробел хорошо визуально разделяет узлы и подчёркивает, что знак равенства — это не разделитель ключа и значения, а просто префикс. Другого такого удобного префикса нет (заметьте, что все специальные символы вводятся в любой раскладке нажатием одной клавиши).

                        Да, именно так. Благодаря префиксам снимаются неоднозначности вида «Обрезать ли ведущий и завершающий переводы строк?», «Обрезать ли отступы?» и «Если обрезать, то на сколько?».
                        • 0
                          Тогда получается, что XML выигрывает в возможностях многострочного значения.

                          А как быть с тем, что поддерживаются только UNIX'овые переводы строк?

                          А вообще язык меня зацепил, жаль что поддержки нет почти.
                          • 0
                            <article>
                                <comment>
                                    <code>Чем же выигрывает?
                            В нём, например, приходится писать без отступов, чтобы в строки не попало лишнего мусора.</code>
                                </comment>
                            </article>
                            


                            А зачем в современной разработке использовать переводы строк отличные от LF? Не в виндовом блокноте же редактируем код :-)

                            Речь о библиотеках? Либа на любом языке пилится за несколько часов.
                            • 0
                              Пилится, но для JSON пилить ничего не нужно.

                              Где-то есть информация на каких языках уже реализовано что бы велосипед не изобретать?

                              И ещё, ИМХО: JSON можно сказать просто для передачи информации, а XML именно для разметки. Tree же умудряется довольно хорошо совмещать эти две функции.
                              • 0
                                Когда-то и JSON был в такой же ситуации. Для XML-то ничего пилить не нужно было. ;-)

                                Есть реализации на D и TS/JS.

                                Для инлайновой разметки tree не очень подходит, в отличие от маркдауна. А для блочной — вполне.
                • 0
                  А как по мне — нормально. Разделение до знака равенства есть? Есть. С точки зрения логики так даже лучше, знак = здесь и правда — маркер начала данных. А ещё так получаются визуально две лексемы вместо трёх, что воспринимается чётче. Я согласен с автором)
          • –1
            Полагаю, вы хотели бы обрезать пробелы по краям строки (trim)? Хм, а если значение — это символ пробела? Неоднозначность получается.
            • –2
              Нет, не хотел. Я хотел разрешить пробел перед значением. Если пробел один — это пробел. Если их два — второй уже значение. Никакой неоднозначности.
              • –4
                Неоднозначность заключается в том, что первый символ после символа равенства иногда включается в значение, а иногда не включается. И вы предлагаете усложнить реализацию исключительно из эстетических, но не практических соображений. Но я всё же, я сторонник принципа KISS.
                • +1
                  первый символ после символа равенства иногда включается в значение, а иногда не включается

                  Первый пробел после равенства никогда не включается в значение. Если первый символ после пробела после равенства — тоже пробел, то он считается, как значение. Элементарно же ж.
          • +8
            А где пример с не экранированными переносами строк?
            Удобство редактирования все так же под вопросом — все эти невидимые символы придется делать видимыми в редакторах.
            И еще вопрос, что вы думаете о Tree в сравнении с Lisp-деревьями?
            • +12
              Примерно так:

              image

              О каких невидимых символах идёт речь?

              Пример с JSON-AST из статьи — это фактически и есть Lisp-дерево:

              [ [ "function",
                  "getEl",
                  [ "id" ],
                  [ "return",
                    [ [ "get",
                        "document" ],
                      [ "call",
                        "getElementById",
                        [ "get", "id" ]
                      ]
                    ]
                  ]
                ]
              ]

              Они не так наглядны, как Tree.
              • +14
                Ну т.е. скопировать текст все так же не получится из-за "=" (даже хуже, так как экранирование реализовано везде).

                Про невидимые символы: вы не слышали о пробелах и табуляции?) А это значит:
                1. Сложности с редактированием документа. Т.е. удобство не 5, а 3 примерно.
                2. Значения, не ограниченные ничем могут появляться сами собой (о поверьте, это огромная проблема).

                Т.е. одно дело мы используем табуляцию/пробелы в языках программирования — там четкое AST и лишние просто игнорируются, но для данных это беда.
                • +1
                  Вырезать по одному символу вначале строки куда проще, чем убрать всё многообразие escape-последовательностей.

                  1. Вы всегда можете настроить свой редактор, чтобы рисовал табуляцию хоть в 10 символов длиной :-)
                  2. О чём тут идёт речь?

                  В Tree тоже чёткое AST. Tree — это и есть самый что ни на есть AST.
                  • +2
                    Вырезать по одному символу вначале строки куда проще, чем убрать всё многообразие escape-последовательностей.

                    Допустим я копирую текст из PHP в JavaScript и т.д. \n везде будет переводом строки.
                    Чтобы убрать \n — мне достаточно простой регулярки заменяющей это на перевод строки (любой редактор). Да, у вас придется заменять перевод_строки= на перевод строки, но в чем достоинство?
                    По поводу пробелов вы уже ответили ниже habrahabr.ru/post/248147/#comment_8229867 и признаете это проблемой.
                    Т.е. в итоге лучше б все таки иметь гарантированные \s \t, чем незамеченные пробелы в начале/конце значения данных.
                    Про AST разница в хранении данных и структуре кода в том, что в коде можно проигнорировать кучу символов (пробелы, переносы строк, табуляцию).
                    var a = 5; Без разницы сколько тут пробелов до var и после точки с запятой. С данными такое не прокатит.
                    • +1
                      Допустим я копирую текст из PHP в JavaScript и т.д. \n везде будет переводом строки.

                      А я, допустим, копирую текст из PHP в HTML и \n больше не будет переводом строки.

                      Чтобы убрать \n — мне достаточно простой регулярки заменяющей это на перевод строки (любой редактор). Да, у вас придется заменять перевод_строки= на перевод строки, но в чем достоинство?

                      В данном случае нет никакой разницы, да.

                      Т.е. в итоге лучше б все таки иметь гарантированные \s \t, чем незамеченные пробелы в начале/конце значения данных.

                      Только в конце. Проблема куда менее значительная, чем проблема редактирования, когда весь текст в одну строку. И проблема эта вполне решаемая. В любом решении можно найти кучу недостатков, вопрос лишь в том, перевешивают ли достоинства эти недостатки.

                      var a = 5; Без разницы сколько тут пробелов до var и после точки с запятой.

                      Ну да, а style guid-ы зачем пишут тогда, раз нет никакой разницы? :-)
                      • +6
                        Только в конце.

                        А у меня редактор режет все \s в конце строки при сохранении файла. Ни пробелов, ни табуляций там никогда не имеется, так что очень даже проблема.
                        • –10
                          Помочь вам настроить редактор так, чтобы он не занимался излишней самодеятельностью?
                    • 0
                      И еще, далеко не всегда визуально удобно видеть перенос строки как перенос строки.
                      <locale>
                          <var name="t1">Прекрасный день\Мы гуляем\nЖизнь боль</var>
                          <var name="t2">Прекрасный день\Мы гуляем\nЖизнь боль</var>
                          <var name="t3">Прекрасный день\Мы гуляем\nЖизнь боль</var>
                      </locale>

                      Здесь удобнее глазом разделять логические составляющие (переменные), чем собственно само значение.
                      • +6
                        А здесь ключи не надо выискивать в середине строки:

                        image

                        И, кстати, вы не заметили, как опечатались в экранировании :-)
                        • +3
                          Это не я, честно, это хабр)

                          Ну да, а style guid-ы зачем пишут тогда, раз нет никакой разницы? :-)

                          Ну все же есть разница в ошибке и в лишнем пробеле в стиле кода?

                          Только в конце. Проблема куда менее значительная, чем проблема редактирования, когда весь текст в одну строку. И проблема эта вполне решаемая. В любом решении можно найти кучу недостатков, вопрос лишь в том, перевешивают ли достоинства эти недостатки.

                          Не только, опять же habrahabr.ru/post/248147/#comment_8229867

                          А здесь ключи не надо выискивать в середине строки:

                          Но при этом на странице видно лишь очень малое количество значений. Для программирования все же важнее работать со структурами, чем с данными — для значений данных другие редакторы.
                          • +1
                            Подлый хабр портит первое экранирование в строке :-)

                            Есть, но всё же несоответствие принятому стилю многими программистами воспринимается не менее рьяно, чем синтаксическая ошибка.

                            Когда как на самом деле. В конце концов, можно прикрутить автофолдинг к редактору.
                            • 0
                              Есть, но всё же несоответствие принятому стилю многими программистами воспринимается не менее рьяно, чем синтаксическая ошибка.

                              Соответствие стилю приводится почти любым редактором нажатием одной кнопки. Поэтому разницы нет сколько пробелов там удалится автоматически. Но с данными… Т.е. разница все же есть и большая.
                              • 0
                                В случае Tree необходимости в нажатии этой кнопки нет, потому как формат практически не допускает вольностей. И это хорошо — не надо всяких бьютификаторов, минификаторов, валидаторов оформления и прочей ерунды.
                                • +3
                                  Ну все правильно, формат допускает только ручное выискивание лишних пробелов и табов — и это вы называете «человекоудобством». Зачем нам стремная автоматизация процесса — даешь перфоленты. Одна ошибка приравнивается к смерти.
                                  • –3
                                    Вы слишком гиперболизируете эту проблему. Инструмент, ненавязчиво подсвечивающий концы строк — не такой уж rocket science.
                                    • +4
                                      А вы гиперболизируете оценки Tree). Там, где по вашему мнению кавычки, скобки и экранирование мешают восприятию, по моему мнению, способствуют автоматизации и скорости работы. Мы все таки не художественные тексты пишем.

                                      Инструмент, ненавязчиво подсвечивающий концы строк — не такой уж rocket science.

                                      Верно, только тогда все преимущества отсутствия скобок вообще исчезают, так как мы по прежнему видим разделители и должны их мысленно парсить. Так то и кавычки можно сделать ненавязчимыми в JSON.
                                      • –3
                                        JSON плох не только и не столько обилием пунктуации, которую приходится куда-то распихивать (запятую в конце не ставь, открывающую скобку ставим в конце строки, закрывающая висит одиноко в начале и тд).
                                        • +2
                                          Ну может и стоит решать эти вопросы? habrahabr.ru/post/248147/#comment_8231413
                                          habrahabr.ru/post/248147/#comment_8230645
                                          Ну и я спрашивала про Lisp в начале обсуждения, вы сказали
                                          Они не так наглядны, как Tree.

                                          Теперь, я надеюсь, я донесла свою точку зрения про наглядность)

                                          (запятую в конце не ставь, открывающую скобку ставим в конце строки, закрывающая висит одиноко в начале и тд).

                                          У вас не менее жесткий набор правил, только основан на табах, = и пробелах. Или у вас можно 2 переноса строк, 2 "=" писать? Или = написать потом перенос строки и т.д.
                                          • –5
                                            Теперь, я надеюсь, я донесла свою точку зрения про наглядность)
                                            Когда кругозор сужается до точки, человек называет эту точку «точкой зрения».

                                            Или у вас можно 2 переноса строк
                                            Можно

                                            2 "=" писать?
                                            Тоже можно.

                                            Или = написать потом перенос строки и т.д.
                                            И даже так можно.
                                            • +2
                                              Когда кругозор сужается до точки, человек называет эту точку «точкой зрения».

                                              Т.е. вы все еще не согласны с моей самой узкой в мире точкой зрения про наглядность? Тогда где аргументы?
                                              Можно

                                              Все три можно никак не повлияют на целостность данных, так?
                                              • –5
                                                Я всё ещё не понимаю что вы пытаетесь доказать.

                                                Разумеется.
                                        • 0
                                          Скобки, по-моему, помогают читать сильно структурированный текст — при помощи редакторов с подсветкой скобок типа Notepad++ — и несколько затрудняют-замедляют его написание. Так что неплохо бы ещё и, в виде, например, макроса, иметь «конвертер туда-сюда»…
                                          • 0
                                            А есть редакторы с подсветкой табов.
                                • 0
                                  Мне в принципе понравилась идея. Поддержу дискуссию, тем, что у товарища наверно консоль на 50 строк вот ему все в одну и надо.

                                  В Поддержку Tree могу сказать только одно, мне кажется или вот на таком конфиге json, tree будет выглядеть лучше?
                                  Много текста
                                  [
                                      {
                                          "title":"Карточка торгов",
                                          "width":6,
                                          "class":"",
                                          "form":[
                                              {
                                                  "type":"textbox",
                                                  "label":"Наименование",
                                                  "required":true,
                                                  "validate":{
                                                  },
                                                  "model":"name",
                                                  "width":12
                                              },
                                              {
                                                  "type":"datebox",
                                                  "label":"Дата публикации в печатном издании",
                                                  "required":true,
                                                  "validate":{
                                                  },
                                                  "model":"publish",
                                                  "width":12
                                              },
                                              {
                                                  "type":"datebox",
                                                  "label":"Дата публикации",
                                                  "required":true,
                                                  "validate":{
                                                  },
                                                  "model":"publish2",
                                                  "width":12
                                              },
                                              {
                                                  "type":"datebox",
                                                  "label":"Дата публикации №2",
                                                  "required":true,
                                                  "validate":{
                                                  },
                                                  "model":"publish3",
                                                  "width":12
                                              }
                                          ]
                                      },
                                      {
                                          "title":"Карточка должника",
                                          "width":6,
                                          "class":"",
                                          "form":[
                                              {
                                                  "type":"selectbox",
                                                  "label":"Тип должника",
                                                  "required":true,
                                                  "validate":{
                                                  },
                                                  "model":"typepay",
                                                  "width":12,
                                                  "collection":{
                                                      "type":"list",
                                                      "mappings":{
                                                          "id":"model.id",
                                                          "value":"model.value"
                                                      },
                                                      "data":{
                                                          "1":"Физическое лицо",
                                                          "2":"Юридическое лицо",
                                                          "3":"Индивидуальный предпрениматель"
                                                      }
                                                  }
                                              },
                                              {
                                                  "type":"textbox",
                                                  "label":"Фамилия",
                                                  "required":true,
                                                  "validate":{
                                                  },
                                                  "padding":"0px 5px 0px 0px",
                                                  "additional":{
                                                      "visible":{
                                                          "typepay":{
                                                              "eq":[1]
                                                          }
                                                      }
                                                  },
                                                  "model":"last_name",
                                                  "width":6
                                              },
                                              {
                                                  "type":"textbox",
                                                  "label":"Имя",
                                                  "required":true,
                                                  "validate":{
                                                  },
                                                  "padding":"0px 0px 0px 5px",
                                                  "additional":{
                                                      "visible":{
                                                          "typepay":{
                                                              "eq":[1]
                                                          }
                                                      }
                                                  },
                                                  "model":"first_name",
                                                  "width":6
                                              },
                                              {
                                                  "type":"textbox",
                                                  "label":"Отчество",
                                                  "required":true,
                                                  "validate":{
                                                  },
                                                  "padding":"0px 5px 0px 0px",
                                                  "additional":{
                                                      "visible":{
                                                          "typepay":{
                                                              "eq":[1]
                                                          }
                                                      }
                                                  },
                                                  "model":"father_name",
                                                  "width":6
                                              },
                                              {
                                                  "type":"textbox",
                                                  "label":"Полное Наименование организации",
                                                  "required":true,
                                                  "validate":{
                                                  },
                                                  "padding":"0px 5px 0px 0px",
                                                  "additional":{
                                                      "visible":{
                                                          "typepay":{
                                                              "eq":[2,3]
                                                          }
                                                      }
                                                  },
                                                  "model":"full_name",
                                                  "width":6
                                              },
                                              {
                                                  "type":"textbox",
                                                  "label":"Краткое Наименование организации",
                                                  "required":true,
                                                  "validate":{
                                                  },
                                                  "padding":"0px 0px 0px 5px",
                                                  "additional":{
                                                      "visible":{
                                                          "typepay":{
                                                              "eq":[2,3]
                                                          }
                                                      }
                                                  },
                                                  "model":"part_name",
                                                  "width":6
                                              },
                                              {
                                                  "type":"textbox",
                                                  "label":"ОГРН",
                                                  "required":true,
                                                  "validate":{
                                                  },
                                                  "padding":"0px 5px 0px 0px",
                                                  "additional":{
                                                      "visible":{
                                                          "typepay":{
                                                              "eq":[2]
                                                          }
                                                      }
                                                  },
                                                  "model":"ogrn",
                                                  "width":6
                                              },
                                              {
                                                  "type":"textbox",
                                                  "label":"ОГРНИП",
                                                  "required":true,
                                                  "validate":{
                                                  },
                                                  "padding":"0px 5px 0px 0px",
                                                  "additional":{
                                                      "visible":{
                                                          "typepay":{
                                                              "eq":[3]
                                                          }
                                                      }
                                                  },
                                                  "model":"ogrn",
                                                  "width":6
                                              },
                                              {
                                                  "type":"textbox",
                                                  "label":"ИНН",
                                                  "required":true,
                                                  "validate":{
                                                  },
                                                  "padding":"0px 0px 0px 5px",
                                                  "additional":{
                                                      "visible":{
                                                          "typepay":{
                                                              "eq":[1,2,3]
                                                          }
                                                      }
                                                  },
                                                  "model":"inn",
                                                  "width":6
                                              }
                                          ]
                                      },
                                      {
                                          "seperator":"clear"
                                      },
                                      {
                                          "title":"Карточка Орагизнатора",
                                          "width":6,
                                          "class":"",
                                          "form":[],
                                          "file":"app/forms/company_cart.json",
                                          "position":0,
                                          "modelprefix":"company."
                                      },
                                      {
                                          "title":"Сведения об имуществе",
                                          "width":6,
                                          "class":"",
                                          "form":[
                                              {
                                                  "type":"textarea",
                                                  "label":"Сведения об имуществе на торгах",
                                                  "required":true,
                                                  "validate":{
                                                  },
                                                  "model":"info_stuff",
                                                  "width":12
                                              },
                                              {
                                                  "type":"textarea",
                                                  "label":"Порядок ознакомления с имуществом",
                                                  "required":true,
                                                  "validate":{
                                                  },
                                                  "model":"oznak",
                                                  "width":12
                                              },
                                              {
                                                  "type":"textbox",
                                                  "label":"Начальная цена продажи",
                                                  "required":true,
                                                  "validate":{
                                                  },
                                                  "padding":"0px 5px 0px 0px",
                                                  "model":"start_cash",
                                                  "width":6
                                              },
                                              {
                                                  "type":"textbox",
                                                  "label":"Шаг торгов",
                                                  "required":true,
                                                  "validate":{
                                                  },
                                                  "padding":"0px 0px 0px 5px",
                                                  "model":"step_cash",
                                                  "width":6
                                              }
                                          ]
                                      },
                                      {
                                          "seperator":"clear"
                                      },
                                      {
                                          "title":"Порядок оформления участия в торгах",
                                          "width":6,
                                          "class":"",
                                          "form":[
                                              {
                                                  "type":"textbox",
                                                  "label":"Порядок предоставления заявок",
                                                  "required":true,
                                                  "validate":{
                                                  },
                                                  "model":"step_add",
                                                  "width":12
                                              },
                                              {
                                                  "type":"textbox",
                                                  "label":"Место предоставления заявок",
                                                  "required":true,
                                                  "validate":{
                                                  },
                                                  "model":"place_add",
                                                  "width":12
                                              },
                                              {
                                                  "type":"datebox",
                                                  "label":"Начало приема заявок",
                                                  "required":true,
                                                  "validate":{
                                                  },
                                                  "padding":"0px 5px 0px 0px",
                                                  "model":"start_date_add",
                                                  "width":6
                                              },
                                              {
                                                  "type":"datebox",
                                                  "label":"Окончание приема заявок",
                                                  "required":true,
                                                  "validate":{
                                                  },
                                                  "padding":"0px 0px 0px 5px",
                                                  "model":"end_date_add",
                                                  "width":6
                                              },
                                              {
                                                  "type":"textarea",
                                                  "label":"Порядок оформления участия в торгах",
                                                  "required":true,
                                                  "validate":{
                                                  },
                                                  "model":"poradok_oform",
                                                  "width":12
                                              },
                                              {
                                                  "type":"textbox",
                                                  "label":"Размер задатка",
                                                  "required":true,
                                                  "validate":{
                                                  },
                                                  "model":"size_precash",
                                                  "width":12
                                              },
                                              {
                                                  "type":"textbox",
                                                  "label":"Информация счета задатка",
                                                  "required":true,
                                                  "validate":{
                                                  },
                                                  "model":"info_schet",
                                                  "width":12
                                              },
                                              {
                                                  "type":"filebox",
                                                  "label":"Договор о задатке",
                                                  "required":true,
                                                  "validate":{
                                                  },
                                                  "filebox":{
                                                      "type_id":"hdogovorzadatok",
                                                      "multiple":false,
                                                      "nofile":"Договор не выбран",
                                                      "type":"type"
                                  
                                                  },
                                                  "model":"dogovor_zadatok",
                                                  "width":12
                                              },
                                              {
                                                  "type":"datebox",
                                                  "label":"Дата начала аукциона",
                                                  "required":true,
                                                  "validate":{
                                                  },
                                                  "model":"start_date",
                                                  "width":12
                                              }
                                          ]
                                      },
                                      {
                                          "title":"Порядки купли-продажи",
                                          "width":6,
                                          "class":"",
                                          "form":[
                                              {
                                                  "type":"textarea",
                                                  "label":"Порядок и срок заключения договора купли-продажи",
                                                  "required":true,
                                                  "validate":{
                                                  },
                                                  "model":"poradok_i_srok",
                                                  "width":12
                                              },
                                              {
                                                  "type":"textarea",
                                                  "label":"Срок платежей, реквезиты",
                                                  "required":true,
                                                  "validate":{
                                                  },
                                                  "model":"srok_pay_req",
                                                  "width":12
                                              },
                                              {
                                                  "type":"filebox",
                                                  "label":"Проект договора купли-продажи",
                                                  "required":true,
                                                  "validate":{
                                                  },
                                                  "filebox":{
                                                      "type_id":"saleresaledogovor",
                                                      "multiple":false,
                                                      "nofile":"Договор не выбран",
                                                      "type":"type"
                                  
                                                  },
                                                  "model":"project_dog",
                                                  "width":12
                                              }
                                          ]
                                      },
                                      {
                                          "seperator":"clear"
                                      }
                                  ]
                                  

                                  • НЛО прилетело и опубликовало эту надпись здесь
                                    • +1
                                      Чуток промахнетесь и вырежите на строку ниже/выше, а то и из середины — и привет, то, что было на одном уровне внезапно стало дочерним элементом. А JSON/XML вам сразу ошибку нарисует и правильно — нефиг резать не глядя.

                                      Лучше уж ошибочный документ, чем синтаксически правильный, но с некорректными данными. Ошибка — это не разборщик такой-сякой-плохой-нехорошый, а вам знак — что-то не в порядке!
                                      • НЛО прилетело и опубликовало эту надпись здесь
                                      • –4
                                        Может останется, а может и не останется. Смотря какой кусок вырезать. Из любого формата можно вырезать кусок так, чтобы он остался wellformed. Контроль целостности передаваемых данных — это задача транспортного слоя, а не формата описания данных.
                                      • 0
                                        Ну да, как-то так:

                                        image

                                        И так далее.
                                        • 0
                                          Такой конфиг и в XML будет выглядеть лучше
                              • –1
                                Кстати, я тут допилил плагин к IDEA — теперь он и пробелы в конце строк делает видимыми, и на пробелы в начале оных ругается:

                                image
                            • 0
                              По поводу s-expressions (Lisp) скажу — они, на мой взгляд,
                              бывают (не всегда!) удобнее HTML, XML, JSON и прочего, когда в документе
                              сравнительно мало текста. Т.е. для, скажем, представления
                              AST какого-либо языка или для задания layout'а (вёрстки, на которую
                              ложится CSS, без наполнения) HTML-страницы — очень хорошо.
                              Скобки — проблема надуманная, при активном
                              использовании обычно становятся незаметными
                              недели через две, если, конечно, редактор имеет правильный
                              autoindent и умеет подсвечивать парные скобки, а при использовании
                              средств типа paredit скобки неплохо помогают в редактировании.

                              Проблемы с s-expressions для представления данных / документов
                              следующие:
                              • если документ преимущественно текстовый — получается некрасиво;
                              • по сравнению с XML, не хватает namespaces. В случае CL есть
                                packages, но их трудно назвать достаточнго гибкой заменой
                                пространств имён для файлов данных;
                              • tooling — XPath/XQuery/Relax NG/etc. В случае использования s-exprs
                                для данных обходимся без этих полезняшек или строим велосипеды.

                              JSON по сравнению с s-exprs поддерживает унифицированное представление
                              dicts (objects), вместо которых в символьных выражениях используются
                              property lists, association lists либо какой-то кастомный синтаксис, специфичный
                              для языка (например, Clojure) или приложения (reader macros в CL).
                              По-моему, это не очень большая проблема, т.к. выразить ассоциативный
                              массив в виде s-exprs таки не сложно.
                              С другой стороны, JSON нет стандартных широко поддерживаемых
                              комментариев и это [очень плохо]. _comment-поля, на мой взгляд — извращение.
                              • 0
                                >> выразить ассоциативный массив в виде s-exprs таки не сложно.
                                Есть же alists:
                                (users 
                                  (name . "Alice")
                                  (age . 20))
                                
                                • 0
                                  Ну а как же
                                  (users 
                                    (:name "Alice")
                                    (:age 20))
                                  
                                  • 0
                                    А что это? (на руби смахивает, хотя знаю я его поверхностно)
                                • 0
                                  Так я же и написал про association lists выше по тексту. Можно ещё
                                  plists (property lists):

                                  (users (:name "Alice" :age 20))
                                  • 0
                                    <занудство>
                                    А разве не так:
                                    (users 
                                      (user 
                                        (name . "Alice")
                                        (age . 20)))
                                    

                                    или
                                    (users 
                                      ((name . "Alice")
                                        (age . 20)))
                                    

                                    ?
                                    Там же ещё может быть
                                    (users 
                                      ((name . "Jane")
                                        (age . 21))
                                      ((name . "Alice")
                                        (age . 20)))
                                    

                                    </занудство>
                              • +61
                                Нужно сначала показывать продукт, а уже потом сравнивать его с чем-то.
                                Пришлось промотать в самый низ, чтобы увидеть как выглядит это чудо.

                                >JSON и YAML для создания иерархий предлагают «списки» и «мапки». Не все структуры данных хорошо представимы с их помощью.
                                >В Tree есть только один тип узлов
                                Одним типом узлов, конечно проще описать чем двумя /sarcasm.
                                А если серьезно, то «списки» это вложенные JSON документы. Какая тут может быть проблема с представлением не понятно.

                                >Как минимум необходима разноцветная подсветка лексем. Очень помогает — автоформатирование, автодополнение и подсветка ошибок
                                Использовать Tree без всего этого будет не мене неудобно

                                >Отсутствие необходимости в экранировании и разэкранировании спецсимволов
                                Только для \n, видимо?

                                >Почти все текстовые форматы не совместимы с бинарными данными.
                                Простите? Что вам мешает хранить «бинарные данные» в JSON?

                                >В Tree нет комментариев
                                Мило

                                >Табуляция
                                Мило

                                >Универсальноть
                                Так и не объяснили что это значит.

                                Кроме того, как я понимаю, в качестве ключа нельзя использовать blob или даже произвольные «строки», например, включающие символ '='?

                                В остальном, если без всяких «языков на его основе», то выглядит неплохо. По сути просто json без лишних скобок и кавычек, что радует.
                                • –24
                                  Нужно сначала показывать продукт, а уже потом сравнивать его с чем-то.

                                  Если сразу показать, то типичная реакция: «ой, фу, я так не привык, не хочу дальше читать, пойду напишу в коментах, что люблю json» Тут же я хотел сначала обрисовать недостатки известных форматов, подчеркнув, что в предлагаемом решении их нет. Вы же испортили себе всё впечатление :-)

                                  Одним типом узлов, конечно проще описать чем двумя /sarcasm.

                                  Одним универсальным проще, чем двумя ограниченными. Пример с AST весьма показателен.

                                  Использовать Tree без всего этого будет не мене неудобно

                                  На самом деле менее. В нём сложно написать что-то нечитаемое или допустить синтаксическую ошибку.

                                  Только для \n, видимо?

                                  Экранированием это можно назвать только с натяжкой, но таки да, в остальных форматах экранировать приходится гораздо большее число символов.

                                  Простите? Что вам мешает хранить «бинарные данные» в JSON?

                                  Я так понимаю вы намекаете на base64, base62 и другие способы конвертации бинарных данных в текстовые? Вот собственно эта фаза перекодировки и мешает. Она не позволяет просто потоком вгрузить файл в память и далее просто ссылаться на его участки — обязательно надо выделять отдельные куски памяти для отдельных декодированных значений.

                                  Так и не объяснили что это значит.

                                  Оно складывается из суммы остальных параметров, так что решил его убрать, а вот табличку не поправил, спасибо.

                                  Кроме того, как я понимаю, в качестве ключа нельзя использовать blob или даже произвольные «строки», например, включающие символ '='?

                                  В качестве имени — нельзя. В качестве ключа — можно. Например, аналогом такого JSON:

                                  {
                                      "a+b=c" : [ 0 , true ],
                                      "\"foo\"" : [ 1.1 , false ]
                                  }
                                  

                                  Будет такой json.tree:

                                  image
                                  • +8
                                    Не смотря на заявления о простате синтаксиса, он все равно мне кажется непонятным. Возьмем ваш последний пример. Почему значения в списках представлены в виде имен, а не значений? Зачем явно указывать слово list, разве несколько значений не будут на это прямо указывать?
                                    • –4
                                      Можно и в виде значений, только тогда придётся как-то различать типы примитивов. Указание чисел и констант в виде имён позволяет не указывать дополнительно эти типы.

                                      Если не указывать list то в случае одного единственного элемента списка будет невозможно понять список там должен быть из одного элемента или же просто этот самый элемент.
                                      • +11
                                        > тогда придётся как-то различать типы примитивов
                                        Но здесь же они тоже не различаются. В синтаксисе нет ничего про типы. А где дополнительно нужно описывать тип? Как-то это не вяжется с парсером в 10 паттернов.
                                        • –2
                                          Типы — это сущности другого уровня — языкового. Для разных языков нужны разные типы, так что не место им на уровне формата.

                                          Типы можно указывать по разному. Например, для языка программирования, где набор типов может расширяться, они могут указываться так:

                                          image

                                          Но для JSON с фиксированным набором типов и простым способом их различения — это излишне.

                                          Транслятор json.tree в json вполне может проанализировать узел-имя и понять, что там число или булево значение, или null, а вот узлы-значения воспринимать как строки.
                                          • +10
                                            Вам не кажется, что наличие таких уровней ухудшает многие параметры, которые вы оценили на 5. Например, размер в сериализованном виде увеличивается от этих list и map, а человекопонятность и удобство редактирования уменьшается.
                                            • –3
                                              Разумеется, JSON модель данных выраженная в Tree формате будет занимать больше места. Точно также Tree модель данных в формате JSON будет будет ещё больше. Это неизбежная цена отображения одного формата на другой.
                                              • +2
                                                Только это не JSON модель данных, javascript. И такая модель данных (со строками, числами, логическими константами, массивами и объектами) существует во многих языках. А вот модели данных как в Tree я не встречал.
                                                • 0
                                                  JS модель данных пошире будет. И вы преувеличиваете универсальность этой модели. Во многих языках в массиве могут быть значения только одного типа. Во многих языках числа и строки представляются множеством разных типов. Во многих языках есть такие структуры как множества, ссылки, матрицы (которые ни разу не массивы массивов). И это я не говорю про многообразие кастомных типов.
                                        • +2
                                          Типы можно различать, используя BSON. А он еще и бинарный формат, да, и конвертируется из обычного JSON.
                                          • +3
                                            BSON — это всё же чисто бинарный формат. Его и руками в редакторе не поредактируешь и в логах не посмотришь. И вообще с ним работать можно лишь через специальные инструменты.
                                            • 0
                                              Ну как это не поредактируешь? Hex-редактор и погнал. Ну а специальные инструменты — это слишком натянуто. Он очень строго типизирован, есть куча готовых реализаций, а своя реализация «на коленке», пишется за пару часов, а то и меньше. С tree тоже придется использовать «специальные инструменты».
                                              UPD: А просматривать можно соответствующий JSON документ.
                                              • –4
                                                HEX редактор — весьма специальный инструмент.

                                                Для Tree и простейшего текстового редактора хватит в большинстве случаев.

                                                Я не сомневаюсь, что можно извертнуться и хоть на ASM-е писать. Но зачем?
                                      • +16
                                        >Если сразу показать
                                        А если не показать, то человеку придется проматывать вниз, чтобы понять о чем вообще речь.
                                        Либо уйти, не читая.

                                        >Тут же я хотел сначала обрисовать недостатки известных форматов, подчеркнув, что в предлагаемом решении их нет. Вы же испортили себе всё впечатление :-)
                                        Нет, не испортил. Таблицу я прочитал до того, как промотал вниз.
                                        Почти в самый конец, потому как в пределах 4 (!!!) экранов не увидел ниодного примера этго чуда,
                                        которое получило оценку 5 почти по всем пунктам

                                        >Одним универсальным проще, чем двумя ограниченными
                                        Чем ограничены эти два формата?
                                        Как уже говорил, «списки», по сути, это вложенные JSON документы.
                                        Массивы это просто синтаксис для таких документов, без необходимости ввода ключей, чтобы не писать в столбик ключи без значений, как вы это делаете в Tree (из примера ниже)

                                        >На самом деле менее.
                                        Вовсе нет. Что там пелена, что здесь.

                                        >В нём сложно написать что-то нечитаемое или допустить синтаксическую ошибку.
                                        Видимо из-за проблем с выразительным средствами.
                                        Как же проблема с = перед значением, которую описала sferrka?
                                        А хранение ключей, которую описал я выше?
                                        А пробелы в ключе, про которые говорил PHmaster ниже?

                                        > форматах экранировать приходится гораздо большее число символов.
                                        У вас перенос строки, если верить примеру выше, просто заменяется на '=', что не сильно лучше \n
                                        Поэтому количество символов, которые нужно экранировать у вас вовсе не меньше, если не больше из-за '='

                                        >Я так понимаю вы намекаете на base64, base62
                                        Нет, не намекаю. Строка в JSON является строкой условно, ничто не мешает вам хранить в ней blob
                                        • НЛО прилетело и опубликовало эту надпись здесь
                                          • +6
                                            Строка в JSON является строкой условно, ничто не мешает вам хранить в ней blob
                                            Ничего условного в ней нет, в спеке вполне однозначно сказано, что это строка из символов Unicode, причём слеши и кавычки нужно ещё и обязательно экранировать. Так что блоб там хранить можно только предварительно конвертировав его в base64 или что-то подобное.
                                            • 0
                                              map — неупорядоченный (ограничение по упорядоченности) ассоциативный (ограничение по уникальности ключей) массив.
                                              list — упорядоченный индексированный (ограничение на индексы — строго последовательно, начиная с 0) массив.

                                              Напомню, что в JSON нужно экранировать:
                                              * перевод строки
                                              * кавычки
                                              * обратный слеш
                                              * пачку управляющих символов

                                              В Tree спецсимвол не допустимый в значениях только один — перевод строки.
                                              • +4
                                                Извините, но эти «ограничения» служат для удобства использования и никак не виляют на выразительность.

                                                В то же время в Tree этого всего нет, а значит придется как-то это где-то специфицировать (как отличить сортированный от несортированного?). Введете TSD и Tree Schema?
                                                Это не простота, это бедность.

                                                > пачку управляющих символов
                                                Эти подлежат «экранированию» по причине того, что просто так с клавиатуры их не ввести.
                                                Остальные, действительно, ограничения, накладываемые форматом, здесь вы правы.

                                                Идея использовать практически голые AST как формат хранения данных мне нравится.
                                                Но то, что вы показываете — сильно недоработанная концепция.
                                                И, пожалуй, его главная проблема — амбициозность разработчика, которая формирует соответствующее отношение к самому проекту.
                                                • 0
                                                  Вы зря недооцениваете стек XML технологий. Их разрабатывали куда более умные люди, чем вы или я. И идея разделения языка и формата — очень здравая, потому как позволяет иметь в рамках одного формата тысячи языков, для которых не надо писать отдельные парсеры.
                                                  • 0
                                                    Почему вы решили, что я его недооцениваю? XML хорошо показал себя в свое время, но сейчас ему находят более эффективные альтернативы. В IT все стремится к упрощению. Почему JSON стал так популярен? Потому, что он прост: не нужна никакая схема, не нужно ничего декларировать — просто используй.

                                                    >И идея разделения языка и формата — очень здравая
                                                    Разве я это отрицал? Я говорил лишь о том, что Tree не решает тех проблем, которые вы нашли в JSON. Во всяком случае, без использования схемы. А если использовать схему, то ваш формат усложняется. Причем это усложнение сразу нивелирует все его плюсы:
                                                    1. Он становится слишком неудобным для использования человеком
                                                    2. Он начинает конкурировать с BSON (так же «удобно» редактировать руками) и Protobuffers, где «сливает» вообще по всем параметрам.
                                                    • –2
                                                      а) А при чём тут схема?
                                                      б) В чём проблема запилить схему? Я вам удочку даю, а вы от меня рыбы требуете.

                                                      1. Вы попробуйте сначала, а потом уже говорите о неудобности.
                                                      2. Вполне себе разумный компромис между компактностью и читаемостью. Всякие BSON и прочие бинарники имеют сильно ограниченное применение. В то время как адекватных применений Tree — гораздо больше.
                                                      • 0
                                                        >А при чём тут схема?
                                                        При том, что ей вы описываете что есть что. Если в языке нет необходимого минимума, то приходится описывать вообще все.

                                                        >В чём проблема запилить схему?
                                                        Только в том, что это нужно сделать. И чем раньше это «нужно» появится, тем хуже.

                                                        >Вы попробуйте сначала, а потом уже говорите о неудобности.
                                                        Пробовал уже. Как только вы для этого предложили нечто похожее на формы Бэкуса-Наура.
                                                        В связи с чем, кстати, появился вопрос: как вам идея использовать вместо вашего решения bison? Он несравнимо более гибок, да и реализация уже есть. Получаем сразу и описание формата и парсеры под все популярные языки.

                                                        >Всякие BSON и прочие бинарники имеют сильно ограниченное применение
                                                        Тем не менее в бинарной области они работать будут лучше чем та спецификация Tree, что вы показываете. А в «небинарной» есть JSON (который, кстати, без проблем конвертируется в BSON).

                                                        > В то время как адекватных применений Tree — гораздо больше.
                                                        Попытка создать инструмент, который делает все, приводит к тому, что он делает все в равной степени плохо. В том смысле, что специализированный инструмент, справился бы с конкретной задачей значительно лучше.
                                                        • 0
                                                          Я уже устал повторять, что Tree — это формат, а не язык. Примеры языков в статье есть и для ник вполне чётко определено что есть что.

                                                          Идея-то хорошая, но боюсь не найду в ближайшее время времени ковыряться с bison.

                                                          Специализированный инструмент справится лучше, только на изучение каждого инструмента нужно время и таскать их все с собой не очень удобно. Плюс ещё и стыкуются они друг с другом плохо.
                                                          • +2
                                                            >Я уже устал повторять, что Tree — это формат, а не язык
                                                            Извините, что утомил вас. Не волнуйтесь, я помню, и это очевидно из его сравнение с JSON, XML, YAML.

                                                            Перефразирую: если формат не предоставляет достаточно конструкций сам по себе, то их придется где-то описывать. Пример с массивами: да, в JSON они нумеруются от 0 и только так. Но в Tree такого нет вообще. Нигде не написано, являются ли дочерние узлы упорядоченными или нет и какие им даются индексы. А это значит, что придется вводить новую спецификацию (схему), для того, чтобы это описать.

                                                            Если вы подразумеваете, что в чистом виде он никогда не будет использоваться, то презентуйте его как мета-формат.

                                                            >только на изучение каждого инструмента нужно время
                                                            Даже если описать все эти языки в рамках одного формата, это не делает изучение более простым

                                                            >таскать их все с собой не очень удобно
                                                            Как это отличается от все-в-одном?

                                                            >Плюс ещё и стыкуются они друг с другом плохо
                                                            Весьма спорное утверждение. Все зависит от конкретного случая.

                                                            Напомню, что сама идея, мне нравится. Мне не нравится её текущая реализация и тот факт, что эту реализацию пытаются выдать за «убийцу» вышеперечисленных форматов.
                                                            • 0
                                                              Вместо того, чтобы хардкодить некоторые типы (например, строки, числа, булевы), а с остальными (например, даты, телефонные номера, гео-координаты) ковыряйтесь как хотите, на мой взгляд лучше дать инструмент объявления своих типов и не навязывать какой-либо набор, «которого хватит всем». Посмотрите на описание языка xml.tree — оно же предельно простое, хоть и не формализованное с помощью каких-либо схем.

                                                              Изучить новый словарь для знакомого синтаксиса куда проще, чем изучить новый синтаксис.

                                                              А вы зря недооцениваете универсальные инструменты. Возьмём вот например нож. Есть нож для рыбы, для мяса, для сыра, для хлеба, для разделки, для удаления костей, для раскрытия раковин устриц, тысячи их. Каждый из них предельно хорош в своей области. А тут прихожу я и говорю, что вот этими двумя типами ножей можно делать всё что угодно. Пусть и не будет того повышенного комфорта, как при использовании устричного ножа. Зато ножи будут взаимозаменяемы, требовать мало места, их не придётся менять каждые 5 минут, подбирая нужный для своего типа нарезаемого продукта.
                                                              • 0
                                                                >Возьмём вот например нож
                                                                приятно видеть человека, видящего перспективность метафорического компьютера :)

                                                                данные: дождевая, вода из-под крана, столовая питьевая, минеральная, газированная сладкая, дистиллированная, вода из лужи, морская, речная, фильтрованная…

                                                                дистиллированная вода — бинарные данные
                                                                вода из-под крана — данные, вводимые пользователем

                                                                формат: мыло, шампунь, ополаскиватель, гель для душа стиральный порошок, средство для мыться посуды, зубная паста, крем для бритья средство для мытья ковров, средство для пола, средство для унитаза, средство для мытья стекол…

                                                                при смешении воды и средства получаем данные в формате

                                                                инструмент: щетка для обуви, зубная щетка, половая тряпка, веник, губка для мытья посуды, скребок для мытья посуды, расческа, щетка для пылесоса, пемза, полотенце…

                                                                То есть, вы утверждаете, что ваш формат — это мыло.
                                                                А ваши оппоненты, что не хотят употреблять молоко в формате сыворотка, когда есть еще масло, сметана, творог, сливки.

                                                                почему бы не провести опрос.
                                                                • 0
                                                                  Ну вы уж совсем мой тезис до абсурда довели :-)
                                                                  Tree тогда уж, это не мыло, а органическая химия, где и преимущественно из одних только атомов углерода собирают самые разнообразные вещества.
                                                      • 0
                                                        Почему JSON стал так популярен? Потому, что он прост: не нужна никакая схема, не нужно ничего декларировать — просто используй.

                                                        На самом деле, не поэтому, а потому, что на веб-клиенте (в браузере) его парсинг был существенно проще и дешевле, чем парсинг xml.

                                                        (xml тоже можно использовать без схемы и деклараций, если что)
                                                        • 0
                                                          или всё же потому, что это серилизатор для ЯваСкрипта? )))
                                                          • 0
                                                            Это не «сериализатор для яваскрипта», это сериализатор, который в некий момент решили использовать в JavaScript как самый простой (потому что чтобы разобрать этот формат, если без учета безопасности, достаточно сделать eval)
                                                            • 0
                                                              ок, делали не столько для ЯваСкрипта.
                                                              Но получил популярность потому, что очень прост для ЯваСкрипта.
                                                              Тот же XML надо вначале распарсить в ДОМ, а уж потом из него вытаскивать данные для скриптов, а с использованием жсона — всё уже распакованно.
                                                              • 0
                                                                А теперь перечитайте, что написано в комменте, на который вы отвечаете:
                                                                потому, что на веб-клиенте (в браузере) его парсинг был существенно проще и дешевле, чем парсинг xml.
                                                                • 0
                                                                  >вначале распарсить в ДОМ
                                                                  SAX
                                                                  • 0
                                                                    SAX на javascript?
                                                                    Но получил популярность потому, что очень прост для ЯваСкрипта.
                                                                    • 0
                                                                      То есть DOM на js вас не смущает?

                                                                      >Но получил популярность потому, что очень прост для ЯваСкрипта.
                                                                      К чему вы это?
                                                                      • 0
                                                                        Разумеется, DOM на js меня не смущает.
                                                                        • 0
                                                                          Если вы клоните к тому, что страница суть тоже xml, то что это меняет? Это запрещает использовать sax-парсеры?
                                                                  • +1
                                                                    По распакованному JSON всё-равно придётся пройтись и преобразовать во внутреннее представление (объектики там всякие, перекрёстные ссылки и тд). Так что особой разницы нет по какому дереву бегать — json, tree или xml.
                                                                    • 0
                                                                      ko.mapping.fromJS(responceJson, viewModel);
                                                                      
                                                                      Сделайте-ка мне, пожалуйста, аналогично с форматом tree :)
                                                                      • 0
                                                                        А в чём проблема?
                                                                        • 0
                                                                          Проблема в том, что распакованный JSON — это объект, который можно напрямую отображать на модель. На выходе же парсера tree — дерево узлов, которые требуется обрабатывать дополнительно.
                                                                          • 0
                                                                            Беспредметный спор. Покажите как вы отобразите JSON модель данных на модель предметной области «на прямую». А я сделаю аналогичное отображение из Tree. А потом сравним у кого сколько «дополнительного» кода получилось.
                                                                            • –1
                                                                              Я же написал выше. Между прочим, реально используемый код.
                                                                              • 0
                                                                                koko.mapping.fromTree(responceTree, viewModel);
                                                                                • 0
                                                                                  Приведите библиотеку. А то по запросу «koko.mapping.fromTree» гуглится какая-то фигня, а без библиотеки сравнить количество «дополнительного» кода не получается.

                                                                                  • –1
                                                                                    А что толку? Реализация будет точно такая же — через паттерн Visitor.
                                                                                    • +1
                                                                                      Какой Visitor в гомогенном дереве, о чем вы?
                                                                                      • –1
                                                                                        Где вы увидели гомогенное дерево?
                                                                                        • +2
                                                                                          Ваш Tree — это гомогенное дерево (это то его достоинство, которым вы так гордитесь)
                                                                                          • –1
                                                                                            Не совсем, имена-то узлов разные, а именно они определяют как транслировать абстрактное дерево в объекты приложения.
                                                                                            • +2
                                                                                              Угу. Вот Visitor подключится (если надо) к делу после трансляции абстрактного дерева в объекты приложения, а не до — а на этой фазе уже не важно, из чего эти объекты смапили.
                                                                                              • –2
                                                                                                Вообще-то мы тут обсуждали именно трансформацию из дерева данных в дерево объектов.
                                                                                                • +2
                                                                                                  … а на этой фазе visitor не используется, потому что дерево данных в вашем случае полностью гомогенно.
                                                              • 0
                                                                >xml тоже можно использовать без схемы и деклараций
                                                                Не спорю, можно. Но несколько сложнее, взять хотя бы проблему выбора между атрибутом и дочерним элементом.

                                                                Хотя, пожалуй, вы правы.
                                                                • 0
                                                                  Если для вас это по каким-то причинам проблема — просто всегда используйте дочерние элементы.
                                                    • +10
                                                      А можно пример того как ваш формат дружит с бинарными данными.
                                                      • 0
                                                        Пример программного кода или пример файла?
                                                        • 0
                                                          Пример файла конечно, зачем мне код.
                                                            • 0
                                                              Отлично, а что будет если в бинарных данных один из символов будет \n?
                                                              • 0
                                                                Очевидно, вместо одного узла-значения будет несколько.
                                                                • –3
                                                                  Это если за \n последует такое же количество табов (что мало вероятно), а если попутно ещё и = встретится так это сделает всё ещё хуже. Что то не вижу я бинарной безопасности в вашем формате.
                                                                  • –2
                                                                    image
                                                                    • +2
                                                                      То есть мне придётся самому в коде разбивать данные на блоки? А чем это лучше экранирования " и \ в json?
                                                                      • 0
                                                                        Зачем самому, если это можно делать автоматически?
                                                                        • 0
                                                                          json тоже это сам делает
                                                                          • 0
                                                                            Разумеется. Вопрос в стоимости этой операции и человекочитаемости.
                                                                            • 0
                                                                              Стоимость этой операции в обоих случаях O(n). В чем вопрос?
                                                                              • 0
                                                                                Вопрос в размере константы.
                                                                                • +1
                                                                                  Во-первых, не в размере константы, а в отношении размеров констант. И вы не сможете адекватно посчитать k для JSON-кодировщика, потому что его реализация очень сильно зависит от возможностей платформы и изворотливости программиста.

                                                                                  Во-вторых, в то время как стоимость кодирования в JSON зависит только от самой строки, в Tree она зависит от строки и ее места в иерархии, что тоже не добавляет счастья.

                                                                                  Нотацию O(f(n)) для того и придумали, чтобы не размениваться на такие мелочи. Для разумной реализации на разумном языке стоимость кодирования и декодирования строкового примитива что в Tree, что в JSON будет сопоставима, и отличия будут вноситься больше на уровне «читаем из буфера vs читаем из потока».
                                                                                  • 0
                                                                                    В JSON многие символы требуют экранирования, что вынуждает работать с байтами индивидуально. Tree же позволяет копировать данные пачками, что гораздо быстрее.
                                                                                    • +1
                                                                                      Каким образом вы гарантируете, что в «пачке» нет переводов строки, если не пройдетесь по каждому байту индивидуально?
                                                                                      • –1
                                                                                        Если пачка прочитана из Tree файла, или через readln(), то переводов строк там точно нет. Если же у нас дикие данные, то при импорте в дерево необходимо пробежаться по ним в поисках переводов строк. Поиск символа в строке — это куда более быстрая операция.
                                                                                        • +3
                                                                                          При импорте в дерево вам нужно не просто «пробежаться… в поисках переводов строк», а точно так же, как и с экранированием, при каждом встреченном символе перевода строки добавить дополнительные символы экранизации: в вашем случае это табы и символ "=", и добавляются они не перед экранируемым символом, а после него. Причем, заметьте, вы не можете экранировать данные и затем вставить их в любое произвольное место в ваше дерево, как это возможно с тем же JSON, так как количество вставляемых в Tree табов после символа перевода строки зависит от контекста, т.е. конкретного места, для которого вы экранируете, а именно — от уровня вложенности объектов в этом месте. А это, в свою очередь, означает, что вы не можете взять некий объект, сериализировать его в Tree-представление и потом использовать сериализованный кусок текста в произвольном месте Tree-файла (или любого другого потока вывода), как это возможно с тем же json и XML. То есть, для сериализации объектов нужно заранее знать всю структуру сериализуемого дерева этих объектов целиком, и при сериализации обходить эту структуру в строгом порядке: от корня к листьям.
                                                                                          • –1
                                                                                            При импорте в дерево не происходит экранирования — только составление списка диапазонов.

                                                                                            static Values
                                                                                            ( T = string )
                                                                                            ( T value , Tree[] childs = [] , string uri = "" ) 
                                                                                            {
                                                                                            	auto chunks = ( cast(string) value ).split( '\n' );
                                                                                            	auto nodes = chunks.map!( chunk =>
                                                                                            		new Tree( "" , chunk , [] , uri )
                                                                                            	);
                                                                                            	return nodes.array;
                                                                                            }
                                                                                            

                                                                                            Функция split не копирует данные, если что, а возвращает так называемые срезы исходного массива.

                                                                                            При сериализации они просто сливаются в выходной поток как есть, без какой-либо обработки.

                                                                                            } else if( this._value.length || prefix.length ) {
                                                                                            	output.write( "=" ~ this._value ~ "\n" );
                                                                                            }
                                                                                            
                                                                                            • +1
                                                                                              В таком слчае так можно сказать про любое другое экранирование, вот например простейшие экранирование " и \
                                                                                              static Values
                                                                                              ( T = string )
                                                                                              ( T value , Tree[] childs = [] , string uri = "" ) 
                                                                                              {
                                                                                              	auto chunks = ( cast(string) value ).split( "\"\\" );
                                                                                              	auto nodes = chunks.map!( chunk =>
                                                                                              		new Tree( "" , chunk , [] , uri )
                                                                                              	);
                                                                                              	return nodes.array;
                                                                                              }
                                                                                              

                                                                                              и потом
                                                                                              } else if( this._value.length || prefix.length ) {
                                                                                              	output.write( "\\" ~ this._value);
                                                                                              }
                                                                                              

                                                                                              Имеются ли тут кардинальные различия? Не думаю.
                                                                                              • 0
                                                                                                У вас при сплите данные теряются. Если разрезать по более чем одному символу, то потом не понятно по какому символу собирать.
                                                                                                • +1
                                                                                                  ну так всегда можно свой split написать который не будет обрезать символы, я просто хотел показать, что по сути экранирование ничем не отличается от вашего разделения.
                                                                                                  • 0
                                                                                                    Экранирование в JSON отличается. Да, можно придумать экранирование, где перед кавычкой и бэкслешем ставится бэкслеш и всё, но чем это:
                                                                                                    { "lalala" :
                                                                                                        "foo\"
                                                                                                    bar\\"
                                                                                                    }
                                                                                                    

                                                                                                    Лучше этого:
                                                                                                    lalala
                                                                                                        =foo"
                                                                                                        =bar\
                                                                                                    

                                                                                                    ?
                                                                                                    • 0
                                                                                                      Экранирование в JSON отличается.

                                                                                                      ничем кроме символов, и того факта что спец символы нужно добавлять до а не после
                                                                                                      Лучше хз, а чем хуже? Между экранированием символом \ и экранированием строкой неопределённой длинны, я бы честно говоря выбрал первый вариант.