Еквівалент XSLT для JSON [закрито]


411

Чи є еквівалент XSLT для JSON? Щось, що дозволяє мені робити перетворення на JSON, як XSLT робить XML.


1
Btw, на якій мові / платформі це було б?
StaxMan

6
@StaxMan XSLT - це стандарт, який реально реалізує у багатьох мовах та платформах, мої запитання спрямовані на подібні зусилля.
luvieere

36
+1 для вашого запитання. Багато людей, здається, не помічають або не люблять XSLT, але це може бути просто реакцією на це багатослівність XML. І справді, оскільки XML поступово випадає з користі, можливостей використовувати XSLT все менше, що шкода! Еквівалент XSLT для JSON був би приголомшливим.
Nicolas Le Thierry d'Ennequin

10
@ NicolasLeThierryd'Ennequin погодився. Багато людей ненавидять XML, тому відхиляють XSLT. Екосистема інструментів XML також важка для розробників Java, що відвертає ще більше людей. Але я був важкий у XSLT в середині 2000-х, і є надзвичайна потужність, яка не має прямого еквівалента поза екосистемою XML. Я люблю в форматі JSON еквівалент!
Зерін

Відповіді:


77

Цікава ідея. Деякі пошуки в Google викликали кілька цікавих сторінок, зокрема:

Сподіваюсь, це допомагає.


10
Так, дякую, саме це я шукав. Шкода, що техніка не користується більшою популярністю, JSON досить часто використовується як формат повернення в службах у стилі REST, і було б непогано мати стандартний спосіб здійснення перетворень.
luvieere

8
Цей код використовує string.eval () ... :-(
dreftymac

Відповідь лише на посилання
Жан-Франсуа Фабре

102

Еквіваленти XSLT для JSON - список кандидатів (інструменти та характеристики)

Інструменти

  1. XSLT

    Ви можете використовувати XSLT для JSON з метою fn: json-to-xml .

    У цьому розділі описано засоби, що дозволяють обробляти дані JSON за допомогою XSLT.

  2. jq

    jq - це як sed для даних JSON - ви можете використовувати їх для зрізування, фільтрування та картографування та перетворення структурованих даних з такою ж легкістю, що sed, awk, grep та друзі дозволяють вам грати з текстом. Існують пакети встановлення для різних ОС.

  3. jj

    JJ - це утиліта командного рядка, яка забезпечує швидкий і простий спосіб отримання або оновлення значень з документів JSON. Він працює від GJSON і SJSON під кришкою.

  4. fx

    Інструмент обробки JSON командного рядка

    • Не потрібно вивчати новий синтаксис
    • Простий JavaScript
    • Форматування та виділення
    • Автономний бінарний
  5. jl

    jl ("JSON lambda") - це крихітна функціональна мова для запитів та маніпулювання JSON.

  6. РОЗКЛАД

    Бібліотека перетворень JSON в JSON, написана на Java, де "специфікація" для перетворення сама є документом JSON.

  7. грон

    Зробіть JSON вдячним! gron перетворює JSON в дискретні завдання, щоб полегшити схоплення за те, що ви хочете, і бачити абсолютний "шлях" до нього. Це полегшує дослідження API, які повертають великі краплі JSON, але мають жахливу документацію.

  8. json

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

  9. json-e

    JSON-e - це система параметризації структури даних для вбудовування контексту в об'єкти JSON. Основна ідея полягає в тому, щоб трактувати структуру даних як "шаблон" і трансформувати її, використовуючи іншу структуру даних як контекст, для створення структури вихідних даних.

  10. JSLT

    JSLT - це повна мова запитів та перетворень для JSON. Мовний дизайн натхненний jq, XPath та XQuery.

  11. JSONata

    JSONata - це легка мова запитів та перетворень даних JSON. Натхненний семантикою «шлях до локації» XPath 3.1, це дозволяє висловлювати складні запити у компактних та інтуїтивних позначеннях.

  12. json-перетворює Останній комітет 1 грудня 2017 року

    Забезпечує рекурсивний, узгоджуючий підхід до перетворення даних JSON. Перетворення визначаються як набір правил, які відповідають структурі об'єкта JSON. Коли відбувається збіг, правило випромінює перетворені дані, необов'язково повторюючись для перетворення дочірніх об'єктів.

  13. jsawk Остання фіксація 4 березня 2015 року

    Jsawk - це як awk, але для JSON. Ви працюєте з масивом об'єктів JSON, прочитаними з stdin, фільтруєте їх за допомогою JavaScript для створення масиву результатів, який друкується до stdout.

  14. yate Останній комітет 13 березня 2017 року

    Тести можна використовувати як docu https://github.com/pasaran/yate/tree/master/tests

  15. jsonpath-object-transform Останній комітет 18 січня 2017 року

    Витягує дані з літералу об'єкта за допомогою JSONPath та генерує нові об’єкти на основі шаблону.

  16. Зв'язання останнього комітету 16 вересня 2013 року

    Сшивання - це бібліотека JavaScript, яка дозволяє форматувати XSLT для об'єктів JSON. Замість використання двигуна шаблонів JavaScript та шаблонів тексту / html, Stapping дає вам можливість використовувати шаблони XSLT - завантажені асинхронно з Ajax та потім кешовані на стороні клієнта - для розбору ваших джерел даних JSON.

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

  • JsonPointer

    Вказівник JSON визначає синтаксис рядка для ідентифікації конкретного значення в документі JSON (Нотація об'єкта JavaScript).

  • JsonPath

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

  • JSPath

    JSPath для JSON - це як XPath для XML. "

  • JSONiq

    Основним джерелом натхнення JSONiq є XQuery, який до цього часу був успішною та продуктивною мовою запитів для напівструктурованих даних


2
Дякую за дуже детальну та корисну посаду. Для того, щоб перетворити однорядний json у читабельну форму, jq (nr.2 у вашому списку) для мене найкращий вибір. Знову дякую!
primehunter

1
Я часто використовую json_pp для гарного друку. Він доступний для багатьох дистрибутивів.
jschnasse

70

Спробуйте JOLT . Це бібліотека перетворень JSON в JSON, написана на Java.

Він був створений спеціально тому, що ми не хотіли грати в гру "JSON -> XML -> XSLT -> XML -> JSON", а використання шаблону для будь-якого досить складного перетворення неможливо.


4
+9000: Це серйозний проект! Huzzah. Демонстрація в Інтернеті з прикладами чудово допомагає піднятися на криву навчання: jolt-demo.appspot.com
kevinarpe

15

jq - легкий і гнучкий процесор JSON командного рядка

Це не на основі шаблонів, як XSLT, а більш стисло. наприклад, для вилучення nameта addressполя в масив:[.name, .address]

У посібнику розглядається приклад перетворення API JSON Twitter (і в посібнику є багато прикладів).


4
Це більш стисло, тому що він здатний набагато менше.
Ihe Onwuka

Я не знайшов, як рекурсивно шукати заданий атрибут у дереві Джсона
Даніель

@Daniel - це .. | .attr_name?те, що ти шукаєш? (від stedolan.github.io/jq/manual/#RecursiveDescent: .. )
ankostis

1
Можливо, не такий здатний як XSLT, але дуже корисний і не такий складний, як XSLT
flq

15

XSLT підтримує JSON, як видно на веб- сайті http://www.w3.org/TR/xslt-30/#json

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


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, наприклад, виклик шаблону, обробка дітей тощо. реалізація повноцінного аналізатора XML для розбору XSLT. Проблема полягає в тому, що для використання XML-шаблонів для перетворення об’єкта JSON вам потрібно проаналізувати XML-шаблони.

Щоб перетворити об’єкт JSON з XML (або HTML, текстом чи будь-яким іншим), потрібно ретельно продумати синтаксис та спеціальні символи, які потрібно використовувати для ідентифікації команд перетворення. Інакше вам доведеться створити аналізатор для вашої власної мови шаблонів. Пройшовши цей шлях, я можу вам сказати, що це не дуже.

Оновлення (12 листопада 2010 р.): Через пару тижнів роботи над моїм аналізатором я зміг її оптимізувати. Шаблони попередньо розбираються, а команди зберігаються як JSON-об'єкти. Правила трансформації - це також об'єкти JSON, тоді як код шаблону - це поєднання HTML та синтаксису домашнього алфавіту, подібного коду оболонки. Мені вдалося перетворити складний документ JSON в HTML, щоб зробити редактор документів. Код становить близько 1 К рядків для редактора (це для приватного проекту, тому я не можу поділитися ним) і близько 990 рядків для коду перетворення JSON (включає команди ітерації, прості порівняння, виклик шаблонів, збереження змінних та оцінку). Планую випустити його під ліцензією MIT. Залиште мені пошту, якщо ви хочете долучитися.


11

Недавно я написав свою власну маленьку бібліотеку, яка намагається залишитися якомога ближче

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

наскільки це можливо (як я міг у будь-якому випадку) у кількох рядках коду JavaScript.

Ось кілька не зовсім тривіальних прикладів використання ...

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

Fiddle: 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-JSON:

Fiddle: 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 vs. 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 vs. 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 wrt. запит до осі предка, як піднімається цим питанням 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

'HTH,


10

Є зараз! Нещодавно я створив бібліотеку json-перетворення саме для цієї мети:

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властивості. Фінал - трансформація ідентичності, яка рекурсивно відповідає.


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>

5

Я дуже втомився від величезної кількості двигунів шаблонів JavaScript, а також усіх їх вбудованих HTML-шаблонів, різних стилів розмітки тощо, і вирішив створити невелику бібліотеку, яка дозволяє форматувати XSLT для структур даних JSON. Ні в якому разі не ракетна наука - це просто JSON проаналізований на XML і потім відформатований з документом XSLT. Це теж швидко, не так швидко, як двигуни шаблонів JavaScript в Chrome, але в більшості інших браузерів він принаймні такий же швидкий, як альтернатива двигуна JS для великих структур даних.


4

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


3

JSONiq є такий стандарт і Зорба З реалізація з відкритим вихідним ++. JSONiq також можна розглядати як XQuery з додаванням JSON як нативного типу даних.



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 тощо) на). Просто із звичайними завданнями (або встановити, дістати), циклічно тощо.

Я маю на увазі, що XSLT - це просто інша мова, і одна з причин, що вона потрібна, полягає в тому, що XML не є об'єктною нотацією, і, таким чином, об'єкти мов програмування не є точно підходящими (імпеданс між ієрархічною моделлю xml та об'єктами / структурами).


Після того як 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, використовуючи той самий.


1
Це не варіант, якщо ви хочете, щоб ваш код зробив це для вас з хорошою продуктивністю.
orad

0

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

(Аналогічний підхід може бути використаний і для JSON.)

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

Відмова: Це мій власний код.


0

Я давно написав адаптер dom для моєї бази обробки Джексона на основі json. Він використовує бібліотеку nu.xom. Отримане дерево дома працює з об'єктами 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 і може в якийсь момент бути включеним у версію про ВНЗ. 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, або повністю оцінив цю опцію ще, але сподіваюся, що я скоріше розберемо її. Просто деякі думки поки що.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.