JSONT или XSLT для JSON

1 Авг
2012

Часто возникает задача преобразования JSON в другие форматы, особенно в XML или HTML. Очевидное решение заключается в использовании языка программирования (ECMAScript, Ruby, …) и DOM-API.
XML можно преобразовать в другой XML-документ, с помощью правил преобразования (XSLT) и применяя эти правила с помощью XSLT-процессора.
Следуя этой концепции, я экспериментировал с набором правил преобразования (записанных в JSON). В результате, по аналогии с XML / XSLT сочетание JSON / JSONT может использоваться для преобразования JSON в любом другом формат.

Пример


Начнем с простого JSON:
{
  "link": {
    "uri": "company.com",
    "title": "company homepage"
  }
}

Мы хотим преобразовать его в HTML ссылку
<a href="company.com">company homepage</a>

Для этого напишем соответствующее правило
{
  "link": "<a href=\"{link.uri}\">{link.title}</a>"
}

И используя процессор jsonT(data, rules) применим правило к JSON данным для получения результата

Принцип работы JSONT


Набором правил является простой словарь. Таким образом, каждое правило — это пара (имя, значение).
Имя правила обычно является выражением для доступа к объекту данных. Значение правила — это строка или функция с одним аргументом, которая вычисляется во время трансформации.
"name": "transformation string"
"name": function(arg){ … }

Правило, заданное строкой, может содержать одно или несколько выражений, заключенных в фигурные скобки
{выражение}

Которое всегда становится строкой.
  • Если выражение ссылается на имя правила, то это правило вычисляется
  • Если результатом выражения является простой тип, то его значение конвертируется в строку
  • Если результатом выражение является массив / словарь, то каждый элемент, обрабатывается соответствующим образом
  • Знак $ как часть выражение заменяется на имя правила
  • Если выражение имеет явный вид
    @
    name(expr), то вызывается функция name, а возвращаемое значение преобразуется в строку

Выходной JSON объект можно получить с помощью ключевого слова self
Имена правил для элементов массива используют синтаксис name[*]. Если используется знак $ в строке правила, * указывает на индекс массива.
Члены входного объекта, которые не имеют правил трансформации и на которые нет ссылкок, а также выражения, которые вычисляются в undefined не образуют выходных данных.

Ещё примеры


Векторная геометрия

{
  "line": {
    "p1": {
      "x": 2,
      "y": 3
    },
 
    "p2": {
      "x": 4,
      "y": 5
    }
  }
}

+
{
  "self": "<svg>{line}</svg>",
  "line": "<line x1=\"{$.p1.x}\" y1=\"{$.p1.y}\"" + "x2=\"{$.p2.x}\" y2=\"{$.p2.y}\" />"
}

=
<svg><line x1="2" y1="3" x2="4" y2="5" /></svg>

HTML список

["red", "green", "blue"]

+
[
  "self": "<ul>n{$}</ul>",
  "self[*]": "  <li>{$}</li>n"
]

=
<ul>
  <li>red</li>
  <li>green</li>
  <li>blue</li>
</ul>

Двухмерный массив и функция-правило

{
  "color": "blue",
  "closed": true,
  "points": [[10,10],[20,10],[20,20],[10,20]]
}

+
{
  "self": "<svg><{closed} stroke=\"{color}\" points=\"{points}\" /></svg>",
  "closed": function(x) { return x ? "polygon" : "polyline"; }, 
  "points[*][*]": "{$} "
}

=
<svg><polygon stroke="blue" points="10 10 20 10 20 20 10 20 " /></svg>

Полезные ссылки:


  1. Оригинальная статья
  2. JSONT module for CommonJS
  3. Обсуждение на stackoverflow.com

Внимание, статья-перевод!
По материалам Хабрахабр.



загрузка...

Комментарии:

Наверх