Equivalente XSLT per JSON [chiuso]


411

Esiste un equivalente XSLT per JSON? Qualcosa che mi permetta di fare trasformazioni su JSON come XSLT fa in XML.


1
A proposito, quale lingua / piattaforma sarebbe su questo?
StaxMan

6
@StaxMan XSLT è uno standard che ha implementazioni effettive in molte lingue e piattaforme, le mie domande si rivolgono a uno sforzo simile.
Luvieere,

36
+1 per la tua domanda. Molte persone sembrano trascurare o non apprezzare XSLT, ma potrebbe essere semplicemente una reazione alla verbosità XML. E in effetti, man mano che XML perde gradualmente favore, ci sono sempre meno opportunità di usare XSLT, il che è un peccato! Un equivalente XSLT per JSON sarebbe fantastico.
Nicolas Le Thierry d'Ennequin,

10
@ NicolasLeThierryd'Ennequin Concordato. Molte persone odiano l'XML e quindi respingono XSLT. L'ecosistema di strumenti XML è anche pesante per gli sviluppatori Java, che allontana ancora più persone. Ma ero molto interessato a XSLT a metà degli anni 2000, e c'è un'enorme potenza che non ha equivalenti diretti al di fuori dell'ecosistema XML. Mi piacerebbe un JSON equivalente!
Zearin,

Risposte:


77

Idea interessante. Alcune ricerche su Google hanno prodotto alcune pagine di interesse, tra cui:

Spero che sia di aiuto.


10
Sì, grazie, è quello che stavo cercando. È un peccato che la tecnica non sia più popolare, JSON è abbastanza spesso usato come formato di ritorno nei servizi in stile REST e sarebbe bello avere un modo standard di implementare trasformazioni ad esso.
luvieere,

8
Questo codice utilizza string.eval () ... :-(
dreftymac il

Link solo risposta
Jean-François Fabre

102

Equivalenti XSLT per JSON: un elenco di candidati (strumenti e specifiche)

Utensili

  1. XSLT

    È possibile utilizzare XSLT per JSON con l'obiettivo di fn: json-to-xml .

    Questa sezione descrive le funzionalità che consentono l'elaborazione dei dati JSON tramite XSLT.

  2. JQ

    jq è come sed per i dati JSON: puoi usarlo per suddividere, filtrare, mappare e trasformare i dati strutturati con la stessa facilità con cui sed, awk, grep e friends ti permettono di giocare con il testo. Esistono pacchetti di installazione per diversi sistemi operativi.

  3. jj

    JJ è un'utilità della riga di comando che fornisce un modo rapido e semplice per recuperare o aggiornare i valori dai documenti JSON. È alimentato da GJSON e SJSON sotto il cofano.

  4. fx

    Strumento di elaborazione JSON da riga di comando

    • Non è necessario imparare una nuova sintassi
    • JavaScript semplice
    • Formattazione ed evidenziazione
    • Binario autonomo
  5. jl

    jl ("JSON lambda") è un minuscolo linguaggio funzionale per interrogare e manipolare JSON.

  6. SCOSSA

    Libreria di trasformazione da JSON a JSON scritta in Java in cui la "specifica" per la trasformazione è essa stessa un documento JSON.

  7. Gron

    Rendi JSON sfidabile! gron trasforma JSON in incarichi discreti per rendere più facile il grep per ciò che si desidera e vedere il "percorso" assoluto. Semplifica l'esplorazione delle API che restituiscono grandi BLOB di JSON ma hanno una documentazione terribile.

  8. jSON

    json è uno strumento CLI veloce per lavorare con JSON. È uno script node.js a file singolo senza deps esterni (diverso da node.js stesso).

  9. JSON-e

    JSON-e è un sistema di parametrizzazione della struttura dati per incorporare il contesto negli oggetti JSON. L'idea centrale è di trattare una struttura di dati come un "modello" e trasformarla, usando un'altra struttura di dati come contesto, per produrre una struttura di dati di output.

  10. JSLT

    JSLT è un linguaggio di query e trasformazione completo per JSON. Il design del linguaggio è ispirato a jq, XPath e XQuery.

  11. JSONata

    JSONata è un linguaggio di query e trasformazione leggero per i dati JSON. Ispirato alla semantica del "percorso di localizzazione" di XPath 3.1, consente di esprimere query sofisticate in una notazione compatta e intuitiva.

  12. json-transforms Last Commit 1 dic 2017

    Fornisce un approccio ricorsivo e di corrispondenza dei modelli alla trasformazione dei dati JSON. Le trasformazioni sono definite come un insieme di regole che corrispondono alla struttura di un oggetto JSON. Quando si verifica una corrispondenza, la regola emette i dati trasformati, facoltativamente ricorrendo alla trasformazione di oggetti figlio.

  13. jsawk Ultimo commit 4 marzo 2015

    Jsawk è come awk, ma per JSON. Lavori con un array di oggetti JSON letti da stdin, filtrali usando JavaScript per produrre un array di risultati che viene stampato su stdout.

  14. yate Last Commit 13 mar 2017

    I test possono essere utilizzati come docu https://github.com/pasaran/yate/tree/master/tests

  15. jsonpath-object-transform Last Commit 18 gennaio 2017

    Estrae i dati da un oggetto letterale utilizzando JSONPath e genera nuovi oggetti basati su un modello.

  16. Stapling Last Commit, 16 settembre 2013

    La pinzatura è una libreria JavaScript che abilita la formattazione XSLT per gli oggetti JSON. Invece di utilizzare un motore di template JavaScript e modelli di testo / html, la pinzatura ti dà l'opportunità di utilizzare i modelli XSLT - caricati in modo asincrono con Ajax e quindi memorizzati nella cache lato client - per analizzare le tue origini dati JSON.

Specifiche:

  • JsonPointer

    Il puntatore JSON definisce una sintassi della stringa per identificare un valore specifico all'interno di un documento JSON (JavaScript Object Notation).

  • JsonPath

    Le espressioni JSONPath si riferiscono sempre a una struttura JSON allo stesso modo in cui le espressioni XPath vengono utilizzate in combinazione con un documento XML

  • JSPath

    JSPath per JSON è come XPath per XML. "

  • JSONiq

    La principale fonte di ispirazione dietro JSONiq è XQuery, che finora è stato dimostrato un linguaggio di query di successo e produttivo per dati semi-strutturati


2
Grazie per il tuo post molto dettagliato e utile. Per trasformare json a una riga in una forma leggibile, jq (n. 2 nella tua lista) è per me la scelta migliore. Grazie ancora!
cacciatore

1
Uso spesso json_pp per una stampa carina. È disponibile per molte distro.
jschnasse,

70

Prova JOLT . È una libreria di trasformazione da JSON a JSON scritta in Java.

È stato creato appositamente perché non volevamo giocare al gioco "JSON -> XML -> XSLT -> XML -> JSON" e non è possibile utilizzare un modello per qualsiasi trasformazione sufficientemente complessa.


4
+9000: questo è un progetto serio! Huzzah. La demo online con esempi aiuta molto a scalare la curva di apprendimento: jolt-demo.appspot.com
kevinarpe,

15

jq - processore JSON da riga di comando leggero e flessibile

Non è basato su template come XSLT, ma più conciso. ad es. per estrarre namee addresscampi in un array:[.name, .address]

Il tutorial illustra un esempio di trasformazione dell'API JSON di Twitter (e il manuale contiene molti esempi).


4
È più conciso perché è capace di molto meno.
Ihe Onwuka,

Non ho trovato come cercare ricorsivamente un determinato attributo in un albero Json
Daniel,

@Daniel è .. | .attr_name?quello che stai cercando? (da stedolan.github.io/jq/manual/#RecursiveDescent: .. )
ankostis

1
Forse non è capace come XSLT ma molto utile e non complicato come XSLT
flq

15

XSLT supporta JSON come visto su http://www.w3.org/TR/xslt-30/#json

XML utilizza parentesi angolari per i token delimitatore, JSON utilizza parentesi graffe, parentesi quadre, ... I. e. Il minor numero di confronti di riconoscimento di token in XML significa che è ottimizzato per la trasformazione dichiarativa, mentre un numero maggiore di confronti, essendo come un'istruzione switch, per motivi di velocità presuppone una previsione speculativa del ramo per cui il codice imperativo nei linguaggi di scripting è utile. Come conseguenza diretta, per diversi mix di dati semi-strutturati, potresti voler confrontare le prestazioni dei motori XSLT e javascript come parte di pagine responsive. Per un payload di dati trascurabile, le trasformazioni potrebbero funzionare altrettanto bene con JSON senza serializzazione XML. La decisione di W3 dovrebbe basarsi su una migliore analisi.


15

Recentemente ho trovato uno strumento che adoro per lo styling JSON: https://github.com/twigkit/tempo . Strumento molto semplice da usare - a mio avviso, è molto più facile da lavorare rispetto a XSLT - non sono necessarie query XPATH.


9
Tempo sembra fantastico se il risultato finale della trasformazione è HTML. E se volessi semplicemente riorganizzare una struttura implicita in una struttura diversa, ma il risultato finale è ancora JSON. Vorrei ancora un analogo di XPath in modo da poter scrivere la trasformazione in modo funzionale.
Toddius Zho

1
Il tempo è davvero molto interessante, grazie. Tuttavia, puoi inviare un xml al browser e un xslt (<? Foglio di stile xsl>) e il tuo browser applicherà il xslt al xml, mostrando una vista definita del tuo xml senza ulteriore codice. Questo dovrebbe valere anche per jsonT / tempo.
Martin Meeser,


11

Dire che la mancanza di strumenti suggerisce che la mancanza di necessità è solo una domanda. Lo stesso potrebbe essere applicato al supporto per X o Y in Linux (Perché preoccuparsi di sviluppare driver e / o giochi di qualità per un sistema operativo di tale minoranza? E perché prestare attenzione a un sistema operativo per il quale le grandi società di giochi e hardware non sviluppano?). Probabilmente le persone che avrebbero bisogno di usare XSLT e JSON finiscono per usare una soluzione piuttosto banale: trasformare JSON in XML. Ma questa non è la soluzione ottimale, vero?

Quando si dispone di un formato JSON nativo e si desidera modificarlo "wysywyg" nel browser, XSLT sarebbe una soluzione più che adeguata al problema. Farlo con la programmazione javascript tradizionale può diventare una seccatura.

In effetti, ho implementato un approccio "dell'età della pietra" a XSLT, usando l'analisi della sottostringa per interpretare alcuni comandi di base per javascript, come chiamare un modello, elaborare i figli, ecc. Certamente implementare un motore di trasformazione con un oggetto JSON è molto più facile di implementando un parser XML completo per analizzare l'XSLT. Il problema è che per utilizzare i modelli XML per trasformare un oggetto JSON è necessario analizzare l'XML dei modelli.

Per trasformare un oggetto JSON con XML (o HTML, o testo o altro) è necessario riflettere attentamente sulla sintassi e sui caratteri speciali che è necessario utilizzare per identificare i comandi di trasformazione. Altrimenti finirai per dover progettare un parser per il tuo linguaggio di template personalizzato. Avendo camminato lungo quel sentiero, posso dirti che non è carino.

Aggiornamento (12 novembre 2010): dopo un paio di settimane di lavoro sul mio parser, sono stato in grado di ottimizzarlo. I modelli vengono preventivamente analizzati e i comandi vengono memorizzati come oggetti JSON. Le regole di trasformazione sono anche oggetti JSON, mentre il codice modello è un mix di HTML e sintassi homebrew simile al codice shell. Sono stato in grado di trasformare un documento JSON complesso in HTML per creare un editor di documenti. Il codice è di circa 1K righe per l'editor (è per un progetto privato, quindi non posso condividerlo) e circa 990 righe per il codice di trasformazione JSON (include comandi di iterazione, confronti semplici, chiamate di modelli, salvataggio e valutazione variabili). Ho intenzione di rilasciarlo con una licenza MIT. Mandami una mail se vuoi essere coinvolto.


11

Ho scritto la mia piccola biblioteca intorno a questo, di recente, che cerca di rimanere il più vicino possibile

5.1 Modello di elaborazione (XSLT REC) https://www.w3.org/TR/xslt#section-Processing-Model

come è possibile (come ho potuto comunque), in poche righe di codice JavaScript.

Ecco alcuni esempi di utilizzo non del tutto banali ...

1. JSON-to-some-markup:

Fiddle: https://jsfiddle.net/YSharpLanguage/kj9pk8oz/10

(ispirato al D.1 Document Example (XSLT REC) https://www.w3.org/TR/xslt#section-Document-Example )

dove questo:

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));

... dà:

<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>

e

2. JSON-to-JSON:

Fiddle: https://jsfiddle.net/YSharpLanguage/ppfmmu15/10

dove questo:

// (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));

... dà:

{
    "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:

Un equivalente JavaScript di ...

XSLT 3.0 REC Sezione 14.4 Esempio: raggruppamento di nodi in base a valori comuni

(a: http://jsfiddle.net/YSharpLanguage/8bqcd0ey/1 )

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

dove...

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)
           });
    })
  );

... dà:

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

Un equivalente JavaScript di ...

Casi d'uso JSONiq Sezione 1.1.2. Raggruppamento di query per JSON

(a: https://jsfiddle.net/YSharpLanguage/hvo24hmk/3 )

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

dove...

/*
  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()

... dà:

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

È anche utile superare i limiti di JSONPath wrt. interrogando contro l'asse degli antenati, come sollevato da questa domanda SO (e certamente da altri).

Ad esempio, come ottenere lo sconto di un articolo di drogheria conoscendo il suo ID di marca, in

{
 "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"
     }
 ]
}

?

Una possibile soluzione è:

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);

... che dà:

Discount of #983: 20

'HTH,


10

C'è adesso! Di recente ho creato una libreria, json-transforms , proprio per questo scopo:

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

Utilizza una combinazione di JSPath , un DSL modellato su XPath e un approccio ricorsivo di pattern matching, ispirato direttamente da XSLT.

Ecco un breve esempio. Dato il seguente oggetto 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 }
  ]
};

Ecco una trasformazione:

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);

Che produce il seguente:

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

Questa trasformazione è composta da tre regole. Il primo corrisponde a qualsiasi automobile prodotta da Honda, emettendo un oggetto con una Hondaproprietà, quindi abbinando ricorsivamente. La seconda regola corrisponde a qualsiasi oggetto con una makerproprietà, producendo le proprietà modele year. Il finale è la trasformazione dell'identità che corrisponde in modo ricorsivo.


9

Come ennesima risposta a una vecchia domanda, suggerirei uno sguardo a DefiantJS . Non è un equivalente XSLT per JSON, è XSLT per JSON. La sezione "Templating" della documentazione include questo esempio:

<!-- 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

Sono stato davvero stanco dell'enorme quantità di motori di template JavaScript disponibili e di tutti i loro modelli HTML in linea, diversi stili di markup, ecc., E ho deciso di creare una piccola libreria che abiliti la formattazione XSLT per le strutture di dati JSON. Non la scienza missilistica in alcun modo: è solo JSON analizzata in XML e quindi formattata con un documento XSLT. È anche veloce, non veloce come i motori di template JavaScript in Chrome, ma nella maggior parte degli altri browser è almeno altrettanto veloce dell'alternativa del motore JS per strutture di dati più grandi.


4

Sto usando Camel route umarshal (xmljson) -> a (xlst) -> marshal (xmljson). Abbastanza efficiente (anche se non perfetto al 100%), ma semplice, se stai già utilizzando Camel.


3

JSONiq è un tale standard e Zorba un'implementazione C ++ open source. JSONiq può anche essere visto come XQuery con l'aggiunta di JSON come tipo di dati nativo.



2

Yate ( https://github.com/pasaran/yate ) è progettato in modo specifico dopo XSLT, presenta JPath (un equivalente XPath naturale per JS), si compila in JavaScript e ha una lunga storia di utilizzo in produzione. È praticamente privo di documenti, ma leggere campioni e test dovrebbe essere sufficiente.


2

JSLT è molto simile a un equivalente JSON di XSLT. È un linguaggio di trasformazione in cui si scrive la parte fissa dell'output nella sintassi JSON, quindi si inseriscono le espressioni per calcolare i valori che si desidera inserire nel modello.

Un esempio:

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

È implementato in Java sopra Jackson.


0

Non sono sicuro che ce ne sia bisogno e per me la mancanza di strumenti suggerisce la mancanza di necessità. JSON viene elaborato meglio come oggetti (come avviene comunque in JS) e in genere si utilizza il linguaggio degli oggetti stessi per eseguire trasformazioni (oggetti Java per Java creati da JSON, lo stesso per Perl, Python, Perl, c #, PHP e così via su). Solo con compiti normali (o set, get), loop e così via.

Voglio dire, XSLT è solo un altro linguaggio, e uno dei motivi per cui è necessario è che XML non è una notazione di oggetti e quindi gli oggetti dei linguaggi di programmazione non sono adattamenti esatti (impedenza tra il modello gerarchico xml e oggetti / strutture).


Dopo che Facebook si è convertito da XML a Json, ho un disperato bisogno di uno strumento come questo.
Joe Soul-portatore

A quale caso stai pensando? Essere in grado di rendere il contenuto JSON simile al modo in cui si renderizzerebbero le risposte XML come HTML? O qualcosa di diverso?
StaxMan,

Mi chiedo quanto sarebbe facile manipolare la trasformazione JSON nel modo oggetto programmatico (w / looping, branching secondo necessità, ecc.) Vs usando il metodo di tipo XSLT, in particolare in caso di trasformazione di un enorme oggetto JSON e dove alcuni dati nella sorgente JSON vengono spostati su / giù alcuni nodi nel JSON di destinazione (quindi non semplicemente una copia diretta della struttura) e dire dove un particolare nodo nel JSON di origine o di destinazione fa parte dell'array di oggetti all'interno del JSON e l'altro JSON (sorgente / destinazione) non lo è .
David,

La facilità è molto soggettiva, quindi sospetto che molto abbia a che fare con ciò a cui siamo abituati.
StaxMan,

Mentre c'è sicuramente bisogno della trasformazione di JSON, hai ragione, è ampiamente soddisfatto da JS. :-) Ma hai visto jq - processore JSON da riga di comando leggero e flessibile ? Soprattutto per quando JS non è disponibile. Direi che la trasformazione è drammaticamente più facile e più intuitiva, persino di JS. ad esempio per estrarre i campi namee address, e metterli in un array:[.name, .address]
13ren

0

Perché non converti JSON in XML usando Mr. Data Coverter , trasformalo in XSLT e poi lo cambi in JSON usando lo stesso.


1
Questa non è un'opzione se vuoi che il tuo codice lo faccia per te con buone prestazioni.
orad,

0

Per un doodle funzionante / prova del concetto di un approccio per utilizzare JavaScript puro insieme al modello familiare e dichiarativo dietro le espressioni corrispondenti di XSLT e i modelli ricorsivi, vedere https://gist.github.com/brettz9/0e661b3093764f496e36

(Un approccio simile potrebbe essere adottato per JSON.)

Si noti che la demo si basa anche sulla chiusura delle espressioni JavaScript 1.8 per comodità nell'espressione dei modelli in Firefox (almeno fino a quando non sarà implementata la forma abbreviata ES6 per i metodi).

Disclaimer: questo è il mio codice.


0

Ho scritto un adattatore dom per il mio framework di elaborazione json basato su jackson molto tempo fa. Utilizza la libreria nu.xom. L'albero dom risultante funziona con le strutture java xpath e xslt. Ho fatto alcune scelte di implementazione che sono piuttosto semplici. Ad esempio, il nodo radice è sempre chiamato "radice", le matrici vanno in un nodo ol con sotto-elementi li (come in html) e tutto il resto è solo un sotto-nodo con un valore primitivo o un altro nodo oggetto.

JsonXmlConverter.java

Uso: JsonObject sampleJson = sampleJson(); org.w3c.dom.Document domNode = JsonXmlConverter.getW3cDocument(sampleJson, "root");


0

Un approccio non ancora fornito è l'uso di un generatore di parser per creare un parser in XSLT che analizza JSON e produce un output XML.

Un'opzione che viene menzionata molto nelle conferenze XML è il generatore di parser ReX ( http://www.bottlecaps.de/rex/ ) - anche se totalmente non documentato sul sito, le ricette sono disponibili sulla ricerca.


0

Potrebbe essere possibile utilizzare XSLT con JSON. La versione 3 di XPath (3.1) XSLT (3.0) e XQuery (3.1) supporta in qualche modo JSON. Questo sembra essere disponibile nella versione commerciale di Saxon e potrebbe ad un certo punto essere incluso nella versione HE. https://www.saxonica.com/html/documentation/functions/fn/parse-json.html

-

Cosa mi aspetterei da una soluzione alternativa:

Vorrei poter immettere JSON per recuperare un set di dati corrispondente e generare JSON o TEXT.

Accedi a proprietà arbitrarie e valuta i valori

Supporto per la logica condizionale

Vorrei che gli script di trasformazione fossero esterni allo strumento, basati sul testo e preferibilmente una lingua comunemente usata.

Alternativa potenziale?

Mi chiedo se SQL potrebbe essere un'alternativa adatta. https://docs.microsoft.com/en-us/sql/relational-databases/json/json-data-sql-server

Sarebbe bello se lo strumento alternativo potesse gestire JSON e XML https://docs.microsoft.com/en-us/sql/relational-database/xml/openxml-sql-server

Non ho ancora provato a convertire gli script XSLT che utilizzo in SQL, o non ho ancora valutato completamente questa opzione, ma spero di esaminarlo più presto. Solo alcuni pensieri finora.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.