XSLT-эквивалент для JSON [закрыто]

411

Есть ли XSLT- эквивалент для JSON? Что-то, что позволяет мне делать преобразования в JSON, как XSLT в XML.

luvieere
источник
1
Кстати, на каком языке / платформе это будет?
StaxMan
6
@StaxMan XSLT - это стандарт, который имеет реальные реализации на многих языках и платформах, мои вопросы направлены на аналогичные усилия.
Luvieere
36
+1 за твой вопрос. Многие люди, кажется, упускают из виду или просто не любят XSLT, но это может быть просто реакцией на многословность XML И действительно, поскольку XML постепенно теряет популярность, возможностей использовать XSLT становится все меньше и меньше, что очень жаль! XSLT-эквивалент для JSON был бы потрясающим.
Николя Ле Тьерри д'Аннекин
10
@ NicolasLeThierryd'Ennequin Согласен. Многие люди ненавидят XML и поэтому отвергают XSLT. XML-экосистема инструментов также сильно зависит от разработчиков Java, что отвлекает еще больше людей. Но я был увлечен XSLT в середине 2000-х, и есть огромная мощь, которая не имеет прямого эквивалента вне экосистемы XML. Я люблю в формате JSON эквивалент!
Зерин

Ответы:

77

Интересная идея. Некоторые поиски в Google дали несколько интересных страниц, в том числе:

Надеюсь это поможет.

Тим
источник
10
Да, спасибо, это то, что я искал. Жаль, что техника не более популярна, JSON довольно часто используется в качестве формата возврата в сервисах в стиле REST, и было бы неплохо иметь стандартный способ реализации преобразований в нем.
Luvieere
8
Этот код использует string.eval () ... :-(
dreftymac
Ссылка только ответ
Жан-Франсуа Фабр
104

XSLT-эквиваленты для JSON - список кандидатов (инструменты и спецификации)

инструменты

  1. XSLT

    Вы можете использовать XSLT для JSON с целью fn: json-to-xml .

    В этом разделе описываются средства, позволяющие обрабатывать данные JSON с использованием XSLT.

  2. JQ

    jq похож на sed для данных JSON - вы можете использовать его для нарезки, фильтрации, отображения и преобразования структурированных данных с той же легкостью, с которой sed, awk, grep и friends позволяют вам играть с текстом. Есть инсталляционные пакеты для разных ОС.

  3. JJ

    JJ - это утилита командной строки, которая обеспечивает быстрый и простой способ извлечения или обновления значений из документов JSON. Это работает на GJSON и SJSON под капотом.

  4. FX

    Средство обработки JSON из командной строки

    • Не нужно изучать новый синтаксис
    • Простой JavaScript
    • Форматирование и выделение
    • Автономный бинарный
  5. JL

    jl ("JSON lambda") - крошечный функциональный язык для запросов и управления JSON.

  6. тряска

    Библиотека преобразования JSON в JSON, написанная на Java, где «спецификация» для преобразования сама является документом JSON.

  7. Грон

    Сделайте JSON greppable! gron преобразует JSON в отдельные назначения, чтобы упростить поиск того, что вы хотите, и увидеть абсолютный «путь» к нему. Это облегчает исследование API, которые возвращают большие двоичные объекты JSON, но имеют ужасную документацию.

  8. JSON

    json - это быстрый инструмент CLI для работы с JSON. Это однофайловый скрипт node.js без внешних deps (кроме самого node.js).

  9. JSON-е

    JSON-e - это система параметризации структуры данных для встраивания контекста в объекты JSON. Основная идея состоит в том, чтобы рассматривать структуру данных как «шаблон» и преобразовывать ее, используя другую структуру данных в качестве контекста, для создания структуры выходных данных.

  10. JSLT

    JSLT - это полный язык запросов и преобразований для JSON. Дизайн языка вдохновлен jq, XPath и XQuery.

  11. JSONata

    JSONata - это легкий язык запросов и преобразований для данных JSON. Вдохновленный семантикой «путь к местоположению» в XPath 3.1, он позволяет выразить сложные запросы в компактной и интуитивно понятной записи.

  12. json-transforms Последний коммит 1 декабря 2017 г.

    Предоставляет рекурсивный подход сопоставления с образцом для преобразования данных JSON. Преобразования определяются как набор правил, которые соответствуют структуре объекта JSON. Когда происходит совпадение, правило генерирует преобразованные данные, необязательно повторяющиеся для преобразования дочерних объектов.

  13. jsawk Последний коммит 4 марта 2015

    Jsawk похож на awk, но для JSON. Вы работаете с массивом JSON-объектов, считываемых из stdin, фильтруете их с помощью JavaScript, чтобы создать массив результатов, который печатается в stdout.

  14. yate Last Commit 13 марта 2017 г.

    Тесты можно использовать как документ https://github.com/pasaran/yate/tree/master/tests

  15. jsonpath-object-transform Последний коммит 18 января 2017 г.

    Извлекает данные из литерала объекта, используя JSONPath, и генерирует новые объекты на основе шаблона.

  16. Сшивание последнего коммита 16 сентября 2013

    Сшивание - это библиотека JavaScript, которая позволяет форматировать XSLT для объектов JSON. Вместо использования механизма шаблонов JavaScript и шаблонов text / html Stapling дает вам возможность использовать шаблоны XSLT - загружаемые асинхронно с Ajax, а затем кэшированные на стороне клиента - для анализа ваших источников данных JSON.

Технические характеристики:

  • JsonPointer

    JSON Pointer определяет строковый синтаксис для определения конкретного значения в документе JavaScript Object Notation (JSON).

  • JsonPath

    Выражения JSONPath всегда ссылаются на структуру JSON так же, как выражения XPath используются в сочетании с документом XML.

  • JSPath

    JSPath для JSON похож на XPath для XML ".

  • JSONiq

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

jschnasse
источник
2
Спасибо за ваш очень подробный и полезный пост. Чтобы преобразовать однострочный json в читаемую форму, jq (nr.2 в вашем списке) является для меня лучшим выбором. Еще раз спасибо!
Primehunter
1
Я часто использую json_pp для красивой печати. Это доступно для многих дистрибутивов.
Jschnasse
70

Попробуйте ДЖОЛТ . Это библиотека преобразования JSON в JSON, написанная на Java.

Он был создан именно потому, что мы не хотели играть в игру «JSON -> XML -> XSLT -> XML -> JSON», и использование шаблона для любого достаточно сложного преобразования невозможно.

Мило С
источник
4
+9000: Это серьезный проект! Возгласы ликования. Демо онлайн с примерами очень помогает подняться по кривой обучения: jolt-demo.appspot.com
kevinarpe
15

jq - легкий и гибкий JSON-процессор командной строки

Он не основан на шаблонах, как XSLT, но более лаконичен. например, для извлечения nameи addressполей в массив:[.name, .address]

В этом руководстве рассматривается пример преобразования JSON API в Twitter (и в руководстве много примеров).

13ren
источник
4
Это более кратко, потому что это способно намного меньше.
Ihe Onwuka
Я не нашел, как рекурсивно искать данный атрибут в дереве Json
Даниэль
@ Даниель - это .. | .attr_name?то, что ты ищешь? (из stedolan.github.io/jq/manual/#RecursiveDescent: .. )
Анкостис
1
Может быть, не такой способный, как XSLT, но очень полезный и не такой сложный, как XSLT
flq
15

XSLT поддерживает JSON, как показано на http://www.w3.org/TR/xslt-30/#json

XML использует угловые скобки для маркеров-разделителей, JSON использует скобки, квадратные скобки, ... I. e. Меньшее число сравнений распознавания токенов в XML означает, что он оптимизирован для декларативного преобразования, в то время как большее количество сравнений, подобно выражению switch, по соображениям скорости предполагают спекулятивный прогноз ветвления, для которого полезен императивный код в языках сценариев. Как прямое следствие, для различных наборов полуструктурированных данных вы можете захотеть сравнить производительность XSLT и движков javascript как части отзывчивых страниц. Для незначительной полезной нагрузки данных преобразования могут работать так же хорошо с JSON без XML-сериализации. Решение W3 должно основываться на лучшем анализе.

Chawathe Vipul S
источник
15

Недавно я нашел инструмент, который мне нравится для стилизации JSON: https://github.com/twigkit/tempo . Очень простой в использовании инструмент - по моему мнению, с ним гораздо проще работать, чем с XSLT - нет необходимости в запросах XPATH.

Дерек Кертис
источник
9
Темп выглядит великолепно, если конечным результатом преобразования является HTML. Но что, если вы просто хотите перестроить подразумеваемую структуру в другую, но в итоге все равно остается JSON. Я все еще хотел бы аналог XPath, чтобы я мог написать преобразование функциональным способом.
Тоддиус Жо
1
Темп очень интересный, действительно, спасибо. Однако вы можете отправить xml в браузер и xslt (<? Xsl-stylesheet>), и ваш браузер применит xslt к xml, показывая определенный вид вашего xml без дополнительного кода. Это также относится и к jsonT / tempo.
Мартин Мизер
11

Сказать, что нехватка инструментов говорит о том, что в этом нет нужды, - это просто вопрос. То же самое можно применить к поддержке X или Y в Linux (Зачем беспокоиться о разработке качественных драйверов и / или игр для такой ОС для меньшинства? И зачем обращать внимание на ОС, для которых не разрабатываются крупные компании, производящие игры и оборудование?). Вероятно, люди, которым понадобится использовать XSLT и JSON, в конечном итоге используют несколько тривиальное решение: преобразование JSON в XML. Но это не оптимальное решение, не так ли?

Если у вас есть собственный формат JSON и вы хотите отредактировать его «wysywyg» в браузере, XSLT будет более чем адекватным решением проблемы. Выполнение этого с традиционным программированием на JavaScript может стать проблемой в заднице.

Фактически, я реализовал подход «каменного века» к XSLT, используя синтаксический анализ подстроки для интерпретации некоторых базовых команд для javascript, таких как вызов шаблона, дочерние процессы и т. Д. Конечно, реализовать механизм преобразования с помощью объекта JSON гораздо проще, чем реализация полноценного синтаксического анализатора XML для анализа XSLT. Проблема в том, что для использования шаблонов XML для преобразования объекта JSON вам необходимо проанализировать XML шаблонов.

Чтобы преобразовать объект JSON с помощью XML (или HTML, или текста, или чего-либо еще), вам нужно тщательно продумать синтаксис и какие специальные символы вам нужно использовать для идентификации команд преобразования. В противном случае вам придётся создавать парсер для вашего собственного языка шаблонов. Пройдя по этому пути, я могу вам сказать, что это не красиво.

Обновление (12 ноября 2010 г.): после нескольких недель работы над парсером я смог оптимизировать его. Шаблоны разбираются заранее, а команды хранятся в виде объектов JSON. Правила преобразования также являются объектами JSON, в то время как код шаблона представляет собой смесь HTML и синтаксиса доморощенного, похожего на код оболочки. Мне удалось преобразовать сложный документ JSON в HTML, чтобы создать редактор документов. Код составляет около 1K строк для редактора (это для частного проекта, поэтому я не могу поделиться им) и около 990 строк для кода преобразования JSON (включает команды итерации, простые сравнения, вызов шаблона, сохранение и оценку переменных). Я планирую выпустить его под лицензией MIT. Напишите мне письмо, если хотите принять участие.

стог
источник
11

Недавно я написал свою собственную маленькую библиотеку, которая старается держаться как можно ближе к

5.1 Модель обработки (XSLT REC) https://www.w3.org/TR/xslt#section-Processing-Model

как это возможно (как я мог в любом случае), в несколько строк кода JavaScript.

Вот несколько не совсем тривиальных примеров использования ...

1. Разметка JSON-to-some:

Скрипка: https://jsfiddle.net/YSharpLanguage/kj9pk8oz/10

(вдохновлено примером документа D.1 (XSLT REC) https://www.w3.org/TR/xslt#section-Document-Example )

где это:

var D1document = {
    type: "document", title: [ "Document Title" ],
    "": [
      { type: "chapter", title: [ "Chapter Title" ],
        "": [
        { type: "section", title: [ "Section Title" ],
          "": [
            { type: "para", "": [ "This is a test." ] },
            { type: "note", "": [ "This is a note." ] }
        ] },
        { type: "section", title: [ "Another Section Title" ],
          "": [
            { type: "para", "": [ "This is ", { emph: "another" }, " test." ] },
            { type: "note", "": [ "This is another note." ] }
        ] }
      ] }
    ] };

var D1toHTML = { $: [
  [ [ function(node) { return node.type === "document"; } ],
    function(root) {
      return "<html>\r\n\
  <head>\r\n\
    <title>\r\n\
      {title}\r\n".of(root) + "\
    </title>\r\n\
  </head>\r\n\
  <body>\r\n\
{*}".of(root[""].through(this)) + "\
  </body>\r\n\
</html>";
    }
  ],
  [ [ function(node) { return node.type === "chapter"; } ],
    function(chapter) {
      return "    <h2>{title}</h2>\r\n".of(chapter) + "{*}".of(chapter[""].through(this));
    }
  ],
  [ [ function(node) { return node.type === "section"; } ],
    function(section) {
      return "    <h3>{title}</h3>\r\n".of(section) + "{*}".of(section[""].through(this));
    }
  ],
  [ [ function(node) { return node.type === "para"; } ],
    function(para) {
      return "    <p>{*}</p>\r\n".of(para[""].through(this));
    }
  ],
  [ [ function(node) { return node.type === "note"; } ],
    function(note) {
      return '    <p class="note"><b>NOTE: </b>{*}</p>\r\n'.of(note[""].through(this));
    }
  ],
  [ [ function(node) { return node.emph; } ],
    function(emph) {
      return "<em>{emph}</em>".of(emph);
    }
  ]
] };

console.log(D1document.through(D1toHTML));

... дает:

<html>
  <head>
    <title>
      Document Title
    </title>
  </head>
  <body>
    <h2>Chapter Title</h2>
    <h3>Section Title</h3>
    <p>This is a test.</p>
    <p class="note"><b>NOTE: </b>This is a note.</p>
    <h3>Another Section Title</h3>
    <p>This is <em>another</em> test.</p>
    <p class="note"><b>NOTE: </b>This is another note.</p>
  </body>
</html>

а также

2. JSON-to-JSON:

Скрипка: https://jsfiddle.net/YSharpLanguage/ppfmmu15/10

где это:

// (A "Company" is just an object with a "Team")
function Company(obj) {
  return obj.team && Team(obj.team);
}

// (A "Team" is just a non-empty array that contains at least one "Member")
function Team(obj) {
  return ({ }.toString.call(obj) === "[object Array]") &&
         obj.length &&
         obj.find(function(item) { return Member(item); });
}

// (A "Member" must have first and last names, and a gender)
function Member(obj) {
  return obj.first && obj.last && obj.sex;
}

function Dude(obj) {
  return Member(obj) && (obj.sex === "Male");
}

function Girl(obj) {
  return Member(obj) && (obj.sex === "Female");
}

var data = { team: [
  { first: "John", last: "Smith", sex: "Male" },
  { first: "Vaio", last: "Sony" },
  { first: "Anna", last: "Smith", sex: "Female" },
  { first: "Peter", last: "Olsen", sex: "Male" }
] };

var TO_SOMETHING_ELSE = { $: [

  [ [ Company ],
    function(company) {
      return { some_virtual_dom: {
        the_dudes: { ul: company.team.select(Dude).through(this) },
        the_grrls: { ul: company.team.select(Girl).through(this) }
      } }
    } ],

  [ [ Member ],
    function(member) {
      return { li: "{first} {last} ({sex})".of(member) };
    } ]

] };

console.log(JSON.stringify(data.through(TO_SOMETHING_ELSE), null, 4));

... дает:

{
    "some_virtual_dom": {
        "the_dudes": {
            "ul": [
                {
                    "li": "John Smith (Male)"
                },
                {
                    "li": "Peter Olsen (Male)"
                }
            ]
        },
        "the_grrls": {
            "ul": [
                {
                    "li": "Anna Smith (Female)"
                }
            ]
        }
    }
}

3. XSLT против JavaScript:

JavaScript-эквивалент ...

XSLT 3.0 REC Раздел 14.4 Пример: группировка узлов на основе общих значений

(по адресу: http://jsfiddle.net/YSharpLanguage/8bqcd0ey/1 )

Ср https://www.w3.org/TR/xslt-30/#grouping-examples

где...

var cities = [
  { name: "Milano",  country: "Italia",      pop: 5 },
  { name: "Paris",   country: "France",      pop: 7 },
  { name: "München", country: "Deutschland", pop: 4 },
  { name: "Lyon",    country: "France",      pop: 2 },
  { name: "Venezia", country: "Italia",      pop: 1 }
];

/*
  Cf.
  XSLT 3.0 REC Section 14.4
  Example: Grouping Nodes based on Common Values

  https://www.w3.org/TR/xslt-30/#grouping-examples
*/
var output = "<table>\r\n\
  <tr>\r\n\
    <th>Position</th>\r\n\
    <th>Country</th>\r\n\
    <th>City List</th>\r\n\
    <th>Population</th>\r\n\
  </tr>{*}\r\n\
</table>".of
  (
    cities.select().groupBy("country")(function(byCountry, index) {
      var country = byCountry[0],
          cities = byCountry[1].select().orderBy("name");
      return "\r\n\
  <tr>\r\n\
    <td>{position}</td>\r\n\
    <td>{country}</td>\r\n\
    <td>{cities}</td>\r\n\
    <td>{population}</td>\r\n\
  </tr>".
        of({ position: index + 1, country: country,
             cities: cities.map(function(city) { return city.name; }).join(", "),
             population: cities.reduce(function(sum, city) { return sum += city.pop; }, 0)
           });
    })
  );

... дает:

<table>
  <tr>
    <th>Position</th>
    <th>Country</th>
    <th>City List</th>
    <th>Population</th>
  </tr>
  <tr>
    <td>1</td>
    <td>Italia</td>
    <td>Milano, Venezia</td>
    <td>6</td>
  </tr>
  <tr>
    <td>2</td>
    <td>France</td>
    <td>Lyon, Paris</td>
    <td>9</td>
  </tr>
  <tr>
    <td>3</td>
    <td>Deutschland</td>
    <td>München</td>
    <td>4</td>
  </tr>
</table>

4. JSONiq против JavaScript:

JavaScript-эквивалент ...

Примеры использования JSONiq 1.1.2. Группировка запросов для JSON

(по адресу: https://jsfiddle.net/YSharpLanguage/hvo24hmk/3 )

Ср http://jsoniq.org/docs/JSONiq-usecases/html-single/index.html#jsongrouping

где...

/*
  1.1.2. Grouping Queries for JSON
  http://jsoniq.org/docs/JSONiq-usecases/html-single/index.html#jsongrouping
*/
var sales = [
  { "product" : "broiler", "store number" : 1, "quantity" : 20  },
  { "product" : "toaster", "store number" : 2, "quantity" : 100 },
  { "product" : "toaster", "store number" : 2, "quantity" : 50 },
  { "product" : "toaster", "store number" : 3, "quantity" : 50 },
  { "product" : "blender", "store number" : 3, "quantity" : 100 },
  { "product" : "blender", "store number" : 3, "quantity" : 150 },
  { "product" : "socks", "store number" : 1, "quantity" : 500 },
  { "product" : "socks", "store number" : 2, "quantity" : 10 },
  { "product" : "shirt", "store number" : 3, "quantity" : 10 }
];

var products = [
  { "name" : "broiler", "category" : "kitchen", "price" : 100, "cost" : 70 },
  { "name" : "toaster", "category" : "kitchen", "price" : 30, "cost" : 10 },
  { "name" : "blender", "category" : "kitchen", "price" : 50, "cost" : 25 },
  {  "name" : "socks", "category" : "clothes", "price" : 5, "cost" : 2 },
  { "name" : "shirt", "category" : "clothes", "price" : 10, "cost" : 3 }
];

var stores = [
  { "store number" : 1, "state" : "CA" },
  { "store number" : 2, "state" : "CA" },
  { "store number" : 3, "state" : "MA" },
  { "store number" : 4, "state" : "MA" }
];

var nestedGroupingAndAggregate = stores.select().orderBy("state").groupBy("state")
( function(byState) {
    var state = byState[0],
        stateStores = byState[1];
    byState = { };
    return (
      (
        byState[state] =
        products.select().orderBy("category").groupBy("category")
        ( function(byCategory) {
            var category = byCategory[0],
                categoryProducts = byCategory[1],
                categorySales = sales.filter(function(sale) {
                  return stateStores.find(function(store) { return sale["store number"] === store["store number"]; }) &&
                         categoryProducts.find(function(product) { return sale.product === product.name; });
                });
            byCategory = { };
            return (
              (
                byCategory[category] =
                categorySales.select().orderBy("product").groupBy("product")
                ( function(byProduct) {
                    var soldProduct = byProduct[0],
                        soldQuantities = byProduct[1];
                    byProduct = { };
                    return (
                      (
                        byProduct[soldProduct] =
                        soldQuantities.reduce(function(sum, sale) { return sum += sale.quantity; }, 0)
                      ),
                      byProduct
                    );
                } ) // byProduct()
              ),
              byCategory
            );
        } ) // byCategory()
      ),
      byState
    );
} ); // byState()

... дает:

[
  {
    "CA": [
      {
        "clothes": [
          {
            "socks": 510
          }
        ]
      },
      {
        "kitchen": [
          {
            "broiler": 20
          },
          {
            "toaster": 150
          }
        ]
      }
    ]
  },
  {
    "MA": [
      {
        "clothes": [
          {
            "shirt": 10
          }
        ]
      },
      {
        "kitchen": [
          {
            "blender": 250
          },
          {
            "toaster": 50
          }
        ]
      }
    ]
  }
]

Также полезно преодолеть ограничения JSONPath в отношении. запрос к оси предка, как это поднимается этим SO вопросом (и, конечно, другими).

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

{
 "prods": [
    {
        "info": {
              "rate": 85
                },
        "grocery": [
                 {
                  "brand": "C",
                  "brand_id": "984"
                 },
                 {
                  "brand": "D",
                  "brand_id": "254"
                 }
                 ],
         "discount": "15"
    },
    {
        "info": {
              "rate": 100
                },
        "grocery": [
                 {
                  "brand": "A",
                  "brand_id": "983"
                 },
                 {
                  "brand": "B",
                  "brand_id": "253"
                 }
                 ],
         "discount": "20"
     }
 ]
}

?

Возможное решение:

var products = {
     "prods": [
        {
            "info": {
                  "rate": 85
                    },
            "grocery": [
                     {
                      "brand": "C",
                      "brand_id": "984"
                     },
                     {
                      "brand": "D",
                      "brand_id": "254"
                     }
                     ],
             "discount": "15"
        },
        {
            "info": {
                  "rate": 100
                    },
            "grocery": [
                     {
                      "brand": "A",
                      "brand_id": "983"
                     },
                     {
                      "brand": "B",
                      "brand_id": "253"
                     }
                     ],
             "discount": "20"
         }
     ]
};

function GroceryItem(obj) {
  return (typeof obj.brand === "string") && (typeof obj.brand_id === "string");
}

    // last parameter set to "true", to grab all the "GroceryItem" instances
    // at any depth:
var itemsAndDiscounts = [ products ].nodeset(GroceryItem, true).
    map(
      function(node) {
        var item = node.value, // node.value: the current "GroceryItem" (aka "$.prods[*].grocery[*]")

            discount = node.parent. // node.parent: the array of "GroceryItem" (aka "$.prods[*].grocery")
                       parent. // node.parent.parent: the product (aka "$.prods[*]")
                       discount; // node.parent.parent.discount: the product discount

        // finally, project into an easy-to-filter form:
        return { id: item.brand_id, discount: discount };
      }
    ),
    discountOfItem983;

discountOfItem983 = itemsAndDiscounts.
  filter
  (
    function(mapped) {
      return mapped.id === "983";
    }
  )
  [0].discount;

console.log("Discount of #983: " + discountOfItem983);

... который дает:

Discount of #983: 20

«НТН,

YSharp
источник
10

Есть сейчас! Я недавно создал библиотеку, json-transforms , именно для этой цели:

https://github.com/ColinEberhardt/json-transforms

Он использует комбинацию JSPath , DSL, смоделированного на XPath, и рекурсивный подход сопоставления с образцом, вдохновленный непосредственно XSLT.

Вот быстрый пример. Учитывая следующий объект JSON:

const json = {
  "automobiles": [
    { "maker": "Nissan", "model": "Teana", "year": 2011 },
    { "maker": "Honda", "model": "Jazz", "year": 2010 },
    { "maker": "Honda", "model": "Civic", "year": 2007 },
    { "maker": "Toyota", "model": "Yaris", "year": 2008 },
    { "maker": "Honda", "model": "Accord", "year": 2011 }
  ]
};

Вот преобразование:

const jsont = require('json-transforms');
const rules = [
  jsont.pathRule(
    '.automobiles{.maker === "Honda"}', d => ({
      Honda: d.runner()
    })
  ),
  jsont.pathRule(
    '.{.maker}', d => ({
      model: d.match.model,
      year: d.match.year
    })
  ),
  jsont.identity
];

const transformed  = jsont.transform(json, rules);

Какой вывод следующий:

{
  "Honda": [
    { "model": "Jazz", "year": 2010 },
    { "model": "Civic", "year": 2007 },
    { "model": "Accord", "year": 2011 }
  ]
}

Это преобразование состоит из трех правил. Первый соответствует любому автомобилю, который сделан Honda, испускает объект со Hondaсвойством, затем рекурсивно сопоставляется. Второе правило соответствует любому объекту с makerсобственности, выдачи сигнала modelи yearсвойства. Финальным является преобразование идентичности, которое рекурсивно совпадает.

Coline
источник
9

В качестве еще одного нового ответа на старый вопрос, я бы предложил взглянуть на DefiantJS . Это не XSLT эквивалент для JSON, то есть XSLT для JSON. Раздел «Шаблонирование» документации включает в себя этот пример:

<!-- Defiant template -->
<script type="defiant/xsl-template">
    <xsl:template name="books_template">
        <xsl:for-each select="//movie">
            <xsl:value-of select="title"/><br/>
        </xsl:for-each>
    </xsl:template>
</script>

<script type="text/javascript">

var data = {
        "movie": [
            {"title": "The Usual Suspects"},
            {"title": "Pulp Fiction"},
            {"title": "Independence Day"}
        ]
    },
    htm = Defiant.render('books_template', data);

console.log(htm);
// The Usual Suspects<br>
// Pulp Fiction<br>
// Independence Day<br>
LS
источник
5

Я очень устал от огромного количества шаблонизаторов JavaScript и всех их встроенных HTML-шаблонов, различных стилей разметки и т. Д. И решил создать небольшую библиотеку, которая позволяет форматировать XSLT для структур данных JSON. В любом случае это не ракетостроение - это просто JSON, анализируемый в XML, а затем форматированный с помощью документа XSLT. Это также быстро, не так быстро, как механизмы шаблонов JavaScript в Chrome, но в большинстве других браузеров это по крайней мере так же быстро, как альтернатива движку JS для больших структур данных.

Бьерн
источник
4

Я использую верблюжий маршрут umarshal (xmljson) -> to (xlst) -> marshal (xmljson). Достаточно эффективно (хотя и не на 100% идеально), но просто, если вы уже используете Camel.

Бен Голдин
источник
3

JSONiq - это такой стандарт, а Zorba - реализация C ++ с открытым исходным кодом. JSONiq также можно рассматривать как XQuery с добавлением JSON как собственного типа данных.

MB21
источник
2

Очень возможно конвертировать JSON с помощью XSLT: вам нужен десериализатор JSON2SAX и сериализатор SAX2JSON.

Пример кода на Java: http://www.gerixsoft.com/blog/json/xslt4json

Андрей Герасика
источник
2

Yate ( https://github.com/pasaran/yate ) специально разработан после XSLT, содержит JPath (естественный эквивалент XPath для JS), компилируется в JavaScript и имеет довольно многолетнюю историю использования. Это практически недокументировано, но чтения образцов и тестов должно быть достаточно.

К Ли
источник
2

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

Пример:

{
  "time": round(parse-time(.published, "yyyy-MM-dd'T'HH:mm:ssX") * 1000),
  "device_manufacturer": .device.manufacturer,
  "device_model": .device.model,
  "language": .device.acceptLanguage
}

Это реализовано в Java поверх Джексона.

Ларс Мариус Гаршол
источник
0

Не слишком уверен, что в этом есть необходимость, и для меня отсутствие инструментов говорит о том, что в этом нет необходимости. JSON лучше всего обрабатывать как объекты (как это делается в JS в любом случае), и вы обычно используете язык самих объектов для выполнения преобразований (Java для объектов Java, созданных из JSON, то же самое для Perl, Python, Perl, c #, PHP и т. Д. на). Просто с обычными заданиями (или set, get), зацикливанием и тд.

Я имею в виду, что XSLT - это просто еще один язык, и одна из причин, по которой он необходим, заключается в том, что XML не является нотацией объектов, и, следовательно, объекты языков программирования не точно соответствуют друг другу (полное сопротивление между иерархической xml-моделью и объектами / структурами).

StaxMan
источник
После того, как Facebook преобразовал из XML в Json, мне остро понадобился такой инструмент.
Джо, приносящий душ
Какой вариант использования вы думаете? Можно ли визуализировать содержимое JSON аналогично тому, как вы представляете ответы XML в виде HTML? Или что-то другое?
StaxMan
Интересно, насколько легко было бы манипулировать JSON-преобразованием способом программного объекта (с циклом, разветвлением и т. Д.) По сравнению с использованием метода типа XSLT, особенно в случае преобразования массивного объекта JSON и перемещения некоторых данных в исходном JSON вверх / вниз по некоторым узлам в целевом JSON (так что это не просто прямая копия структуры) и скажем, где конкретный узел в исходном или целевом JSON является частью массива объектов в JSON, а другой JSON (источник / цель) не является ,
Дэвид
Легкость очень субъективна, поэтому я подозреваю, что многое из этого связано с тем, к чему привык.
StaxMan
Хотя есть определенная необходимость в преобразовании JSON, вы правы, в значительной степени это соответствует JS. :-) Но видели ли вы jq - легкий и гибкий процессор командной строки JSON ? Особенно когда JS недоступен. Я бы сказал, что трансформация намного проще и интуитивнее, чем в JS. Например, чтобы извлечь поля nameи address, и поместить их в массив:[.name, .address]
13ren
0

Почему бы вам не преобразовать JSON в XML с помощью Mr. Data Coverter , преобразовать его с помощью XSLT и затем изменить его обратно на JSON, используя то же самое.

user1058322
источник
1
Это не вариант, если вы хотите, чтобы ваш код делал это для вас с хорошей производительностью.
orad
0

Рабочий дудл / доказательство концепции подхода к использованию чистого JavaScript вместе со знакомым и декларативным шаблоном, лежащим в основе соответствующих выражений XSLT и рекурсивных шаблонов, см. По адресу https://gist.github.com/brettz9/0e661b3093764f496e36.

(Аналогичный подход может быть использован для JSON.)

Обратите внимание, что демонстрационная версия также использует закрытие выражений JavaScript 1.8 для удобства выражения шаблонов в Firefox (по крайней мере до тех пор, пока не будет реализована краткая форма ES6 для методов).

Отказ от ответственности: это мой собственный код.

Бретт Замир
источник
0

Я давно написал dom-адаптер для моей платформы обработки json. Он использует библиотеку nu.xom. Результирующее дерево dom работает с java xpath и xslt. Я сделал несколько вариантов реализации, которые довольно просты. Например, корневой узел всегда называется «корнем», массивы переходят в узел ol с вложенными элементами li (как в html), а все остальное - просто подчиненный узел с примитивным значением или другой объектный узел.

JsonXmlConverter.java

Применение: JsonObject sampleJson = sampleJson(); org.w3c.dom.Document domNode = JsonXmlConverter.getW3cDocument(sampleJson, "root");

Жиль ван Гурп
источник
0

Один из подходов, который еще не дан, заключается в использовании генератора синтаксических анализаторов для создания синтаксического анализатора в XSLT, который анализирует JSON и создает вывод XML.

Одним из вариантов, который часто упоминается на конференциях XML, является генератор синтаксических анализаторов ReX ( http://www.bottlecaps.de/rex/ ) - хотя на сайте он полностью недокументирован, рецепты доступны при поиске.

Том Хиллман
источник
0

Может быть возможно использовать XSLT с JSON. Версон 3 из XPath (3.1) XSLT (3.0) и XQuery (3.1) поддерживает JSON в некотором роде. Похоже, это доступно в коммерческой версии Saxon и может в какой-то момент быть включено в версию HE. https://www.saxonica.com/html/documentation/functions/fn/parse-json.html

-

Что бы я ожидал от альтернативного решения:

Я хотел бы иметь возможность ввода JSON для получения соответствующего набора данных и вывода JSON или TEXT.

Доступ к произвольным свойствам и оценка значений

Поддержка условной логики

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

Потенциальная альтернатива?

Интересно, может ли SQL быть подходящей альтернативой. https://docs.microsoft.com/en-us/sql/relational-databases/json/json-data-sql-server

Было бы неплохо, если бы альтернативный инструмент мог обрабатывать JSON и XML https://docs.microsoft.com/en-us/sql/relational-databases/xml/openxml-sql-server

Я еще не пытался преобразовать скрипты XSLT, которые я использую, в SQL, или еще не полностью оценил эту опцию, но я надеюсь рассмотреть ее в ближайшее время. Просто некоторые мысли до сих пор.

Onceler
источник