Setara XSLT untuk JSON [ditutup]

411

Apakah ada XSLT yang setara untuk JSON? Sesuatu untuk memungkinkan saya melakukan transformasi pada JSON seperti XSLT terhadap XML.

luvieere
sumber
1
Btw, bahasa / platform apa ini?
StaxMan
6
@StaxMan XSLT adalah standar yang memiliki implementasi aktual dalam banyak bahasa dan platform, pertanyaan saya menargetkan upaya yang sama.
luvieere
36
+1 untuk pertanyaan Anda. Banyak orang tampaknya mengabaikan atau tidak menyukai XSLT, tetapi itu mungkin hanya reaksi terhadap XML verbosity. Dan memang, karena XML secara bertahap tidak disukai, ada semakin sedikit peluang untuk menggunakan XSLT, yang sangat disayangkan! Setara XSLT untuk JSON akan luar biasa.
Nicolas Le Thierry d'Ennequin
10
@ NicolasLeThierryd'Ennequin Setuju. Banyak orang membenci XML, dan karenanya mengabaikan XSLT. Ekosistem alat XML juga berat di Jawa devs, yang memalingkan lebih banyak orang. Tapi saya sangat menyukai XSLT pada pertengahan 2000-an, dan ada kekuatan luar biasa yang tidak memiliki padanan langsung di luar ekosistem XML. Saya akan senang setara JSON!
Zearin

Jawaban:

77

Ide yang menarik. Beberapa pencarian di Google menghasilkan beberapa halaman yang menarik, termasuk:

Semoga ini membantu.

Tim
sumber
10
Yup, terima kasih, itulah yang saya cari. Sayang sekali teknik ini tidak lebih populer, JSON cukup sering digunakan sebagai format pengembalian dalam layanan gaya REST dan akan menyenangkan untuk memiliki cara standar menerapkan transformasi untuk itu.
luvieere
8
Kode ini menggunakan string.eval () ... :-(
dreftymac
Hanya tautan jawaban
Jean-François Fabre
102

Setara XSLT untuk JSON - daftar kandidat (alat dan spesifikasi)

Alat

  1. XSLT

    Anda dapat menggunakan XSLT untuk JSON dengan tujuan fn: json-to-xml .

    Bagian ini menjelaskan fasilitas yang memungkinkan data JSON untuk diproses menggunakan XSLT.

  2. jq

    jq seperti sed untuk data JSON - Anda dapat menggunakannya untuk mengiris dan memfilter dan memetakan dan mengubah data terstruktur dengan kemudahan yang sama seperti sed, awk, grep, dan teman-teman memungkinkan Anda bermain dengan teks. Ada paket instal untuk OS yang berbeda.

  3. jj

    JJ adalah utilitas baris perintah yang menyediakan cara cepat dan sederhana untuk mengambil atau memperbarui nilai dari dokumen JSON. Ini didukung oleh GJSON dan SJSON di bawah tenda.

  4. fx

    Alat pengolah JSON command-line

    • Tidak perlu mempelajari sintaks baru
    • JavaScript polos
    • Memformat dan menyorot
    • Biner mandiri
  5. jl

    jl ("JSON lambda") adalah bahasa fungsional kecil untuk query dan memanipulasi JSON.

  6. SENTAKAN

    JSON ke perpustakaan transformasi JSON ditulis dalam Java di mana "spesifikasi" untuk transformasi itu sendiri adalah dokumen JSON.

  7. gron

    Buat JSON dapat diterima! gron mengubah JSON menjadi penugasan tersendiri untuk membuatnya lebih mudah memahami apa yang Anda inginkan dan melihat 'jalur' absolut ke sana. Ini memudahkan eksplorasi API yang mengembalikan gumpalan besar JSON tetapi memiliki dokumentasi yang mengerikan.

  8. json

    json adalah alat CLI cepat untuk bekerja dengan JSON. Ini adalah skrip node.js file tunggal tanpa deps eksternal (selain node.js itu sendiri).

  9. json-e

    JSON-e adalah sistem parameterisasi struktur data untuk menyematkan konteks pada objek JSON. Gagasan utamanya adalah memperlakukan struktur data sebagai "templat" dan mengubahnya, menggunakan struktur data lain sebagai konteks, untuk menghasilkan struktur data keluaran.

  10. JSLT

    JSLT adalah bahasa permintaan dan transformasi lengkap untuk JSON. Desain bahasa terinspirasi oleh jq, XPath, dan XQuery.

  11. JSONata

    JSONata adalah bahasa query dan transformasi yang ringan untuk data JSON. Terinspirasi oleh semantik 'lintasan lokasi' XPath 3.1, ini memungkinkan pertanyaan canggih diungkapkan dalam notasi yang ringkas dan intuitif.

  12. json-transforms Last Commit 1 Des 2017

    Memberikan pendekatan rekursif, pencocokan pola untuk mengubah data JSON. Transformasi didefinisikan sebagai seperangkat aturan yang cocok dengan struktur objek JSON. Ketika kecocokan terjadi, aturan memancarkan data yang diubah, secara opsional berulang untuk mengubah objek anak.

  13. jsawk Terakhir berkomitmen 4 Maret 2015

    Jsawk seperti awk, tapi untuk JSON. Anda bekerja dengan larik objek JSON yang dibaca dari stdin, memfilternya menggunakan JavaScript untuk menghasilkan larik hasil yang dicetak ke stdout.

  14. yate Commit Terakhir 13 Mar 2017

    Tes dapat digunakan sebagai docu https://github.com/pasaran/yate/tree/master/tests

  15. jsonpath-object-transform Commit Terakhir Jan 18, 2017

    Menarik data dari objek literal menggunakan JSONPath dan menghasilkan objek baru berdasarkan templat.

  16. Stapling Last Commit 16 Sep 2013

    Stapling adalah pustaka JavaScript yang memungkinkan pemformatan XSLT untuk objek JSON. Alih-alih menggunakan mesin templating JavaScript dan templat teks / html, Stapling memberi Anda kesempatan untuk menggunakan templat XSLT - dimuat secara asinkron dengan Ajax dan kemudian sisi klien di-cache - untuk mengurai sumber data JSON Anda.

Spesifikasi:

  • JsonPointer

    JSON Pointer mendefinisikan sintaksis string untuk mengidentifikasi nilai tertentu dalam dokumen JavaScript Object Notation (JSON).

  • JsonPath

    Ekspresi JSONPath selalu merujuk ke struktur JSON dengan cara yang sama seperti ekspresi XPath digunakan dalam kombinasi dengan dokumen XML

  • JSPath

    JSPath untuk JSON seperti XPath untuk XML. "

  • JSONiq

    Sumber utama inspirasi di balik JSONiq adalah XQuery, yang telah terbukti sejauh ini merupakan bahasa permintaan yang sukses dan produktif untuk data semi-terstruktur

Jschnasse
sumber
2
Terima kasih atas postingan Anda yang sangat memuaskan dan bermanfaat. Untuk mengubah json satu baris menjadi bentuk yang dapat dibaca, jq (nr.2 dalam daftar Anda) bagi saya adalah pilihan terbaik. Terima kasih lagi!
primehunter
1
Saya sering menggunakan json_pp untuk mencetak cantik. Ini tersedia untuk banyak distro.
jschnasse
70

Coba JOLT . Ini adalah perpustakaan transformasi JSON ke JSON yang ditulis dalam Java.

Itu dibuat khusus karena kami tidak ingin memainkan permainan "JSON -> XML -> XSLT -> XML -> JSON", dan menggunakan templat untuk setiap transformasi yang cukup kompleks tidak dapat dipelihara.

Milo S
sumber
4
+9000: Ini adalah proyek serius! Sabas. Demo online dengan contoh-contoh sangat membantu untuk menaiki kurva belajar: jolt-demo.appspot.com
kevinarpe
15

jq - prosesor JSON baris perintah yang ringan dan fleksibel

Ini bukan berbasis template seperti XSLT, tetapi lebih ringkas. misalnya untuk mengekstrak namedan addressbidang ke dalam array:[.name, .address]

The tutorial berjalan melalui contoh mengubah JSON API Twitter (dan pengguna memiliki banyak contoh).

13rn
sumber
4
Itu lebih ringkas karena ia mampu jauh lebih sedikit.
Ihe Onwuka
Saya tidak menemukan cara mencari atribut yang diberikan secara rekursif di pohon Json
Daniel
@Aniel adalah .. | .attr_name?apa yang Anda cari? (dari stedolan.github.io/jq/manual/#RecursiveDescent: .. )
ankostis
1
Mungkin tidak mampu seperti XSLT tetapi sangat bermanfaat dan tidak serumit XSLT
flq
15

XSLT mendukung JSON seperti yang terlihat di http://www.w3.org/TR/xslt-30/#json

XML menggunakan kurung sudut untuk token pembatas, JSON menggunakan kurung kurawal, kurung siku, ... I. e. Perbandingan token pengakuan XML yang lebih sedikit berarti dioptimalkan untuk transformasi deklaratif, sedangkan lebih banyak perbandingan, seperti pernyataan switch, karena alasan kecepatan mengasumsikan prediksi cabang spekulatif bahwa kode imperatif dalam bahasa skrip berguna untuk. Sebagai konsekuensi langsung, untuk campuran data semi-terstruktur yang berbeda, Anda mungkin ingin membandingkan kinerja XSLT dan mesin javascript sebagai bagian dari halaman responsif. Untuk muatan data yang dapat diabaikan, transformasi mungkin bekerja dengan baik dengan JSON tanpa serialisasi XML. Keputusan W3 harus didasarkan pada analisis yang lebih baik.

Chawathe Vipul S
sumber
15

Baru-baru ini saya menemukan alat yang saya sukai untuk menata JSON: https://github.com/twigkit/tempo . Alat yang sangat mudah digunakan - menurut saya, jauh lebih mudah digunakan daripada XSLT - tidak perlu untuk pertanyaan XPATH.

Derek Curtis
sumber
9
Tempo tampak hebat jika hasil akhir dari transformasi adalah HTML. Tetapi bagaimana jika Anda hanya ingin mengatur ulang struktur tersirat menjadi yang berbeda, namun hasil akhirnya masih JSON. Saya masih menginginkan analog dari XPath sehingga saya dapat menulis transformasi secara fungsional.
Toddius Zho
1
Tempo memang sangat menarik terima kasih. Namun Anda dapat mengirim xml ke browser dan xslt (<? Xsl-stylesheet>) dan browser Anda akan menerapkan xslt ke xml, menampilkan tampilan yang ditentukan dari xml Anda tanpa kode lebih lanjut. Ini seharusnya juga berlaku untuk jsonT / tempo.
Martin Meeser
11

Untuk mengatakan kurangnya alat menyarankan kurangnya kebutuhan hanya mengemis pertanyaan. Hal yang sama dapat diterapkan untuk dukungan untuk X atau Y di Linux (Mengapa repot-repot mengembangkan driver dan / atau game berkualitas untuk OS minoritas seperti itu? Dan mengapa memperhatikan OS yang tidak dikembangkan oleh perusahaan besar dan perangkat keras?). Mungkin orang-orang yang perlu menggunakan XSLT dan JSON akhirnya menggunakan solusi yang agak sepele: Mengubah JSON menjadi XML. Tapi itu bukan solusi optimal, bukan?

Ketika Anda memiliki format JSON asli dan Anda ingin mengeditnya "wysywyg" di browser, XSLT akan menjadi solusi yang lebih dari cukup untuk masalah tersebut. Melakukan hal itu dengan pemrograman javascript tradisional bisa menjadi menyebalkan.

Bahkan, saya telah menerapkan pendekatan "zaman batu" ke XSLT, menggunakan substring parsing untuk menafsirkan beberapa perintah dasar untuk javascript, seperti memanggil templat, memproses anak-anak, dll. Tentu saja menerapkan mesin transformasi dengan objek JSON jauh lebih mudah daripada mengimplementasikan parser XML lengkap untuk mengurai XSLT. Masalahnya adalah, bahwa untuk menggunakan templat XML untuk mengubah objek JSON Anda harus menguraikan XML templat.

Untuk mentransformasi objek JSON dengan XML (atau HTML, atau teks atau apa pun), Anda perlu memikirkan dengan seksama tentang sintaks dan karakter khusus apa yang perlu Anda gunakan untuk mengidentifikasi perintah transformasi. Kalau tidak, Anda akhirnya harus merancang parser untuk bahasa templating kustom Anda sendiri. Setelah berjalan melalui jalan itu, saya dapat memberi tahu Anda bahwa itu tidak cantik.

Pembaruan (12 Nov 2010): Setelah beberapa minggu mengerjakan parser saya, saya sudah bisa mengoptimalkannya. Templat diuraikan sebelumnya dan perintah disimpan sebagai objek JSON. Aturan transformasi juga objek JSON, sedangkan kode templat adalah campuran dari HTML dan sintaksis homebrew yang mirip dengan kode shell. Saya sudah bisa mengubah dokumen JSON yang kompleks menjadi HTML untuk membuat editor dokumen. Kode ini sekitar 1K baris untuk editor (ini untuk proyek pribadi jadi saya tidak bisa membagikannya) dan sekitar 990 baris untuk kode transformasi JSON (termasuk perintah iterasi, perbandingan sederhana, panggilan templat, penyimpanan variabel dan evaluasi). Saya berencana untuk merilisnya di bawah lisensi MIT. Kirimi saya surat jika Anda ingin terlibat.

Rick
sumber
11

Saya menulis perpustakaan kecil saya sendiri di sekitar ini, baru-baru ini, yang mencoba untuk tetap sedekat itu

5.1 Model Pemrosesan (XSLT REC) https://www.w3.org/TR/xslt#section-Process--Model

seperti yang dimungkinkan (seperti yang saya bisa tetap), dalam beberapa baris kode JavaScript.

Berikut adalah beberapa contoh penggunaan yang tidak sepenuhnya sepele ...

1. JSON-to-some-markup:

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

(terinspirasi oleh Contoh Dokumen D.1 (XSLT REC) https://www.w3.org/TR/xslt#section-Document-Example )

dimana ini:

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

... memberi:

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

dan

2. JSON-to-JSON:

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

dimana ini:

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

... memberi:

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

Setara dengan JavaScript ...

XSLT 3.0 REC Bagian 14.4 Contoh: Pengelompokan Node berdasarkan Nilai Umum

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

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

dimana...

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

... memberi:

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

Setara dengan JavaScript ...

JSONiq Use Cases Bagian 1.1.2. Kueri Pengelompokan untuk JSON

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

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

dimana...

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

... memberi:

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

Ini juga berguna untuk mengatasi keterbatasan JSONPath wrt. menanyakan terhadap sumbu leluhur, seperti yang diajukan oleh pertanyaan SO ini (dan tentu saja yang lain).

Misalnya, bagaimana cara mendapatkan diskon dari barang grosir mengetahui id mereknya, di

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

?

Solusi yang mungkin adalah:

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

... pemberian yang mana:

Discount of #983: 20

'HTH,

YSharp
sumber
10

Ada sekarang! Saya baru-baru ini membuat perpustakaan, json-transforms , tepatnya untuk tujuan ini:

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

Ini menggunakan kombinasi JSPath , DSL yang dimodelkan pada XPath, dan pendekatan pencocokan pola rekursif, terinspirasi langsung oleh XSLT.

Ini contoh singkatnya. Diberikan objek JSON berikut:

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

Inilah transformasi:

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

Yang menghasilkan sebagai berikut:

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

Transformasi ini terdiri dari tiga aturan. Yang pertama cocok dengan mobil apa pun yang dibuat oleh Honda, memancarkan objek dengan Hondaproperti, kemudian secara rekursif cocok. Aturan kedua cocok dengan objek apa pun dengan makerproperti, mengeluarkan modeldan yearproperti. Final adalah transformasi identitas yang cocok secara rekursif.

ColinE
sumber
9

Sebagai jawaban baru untuk pertanyaan lama, saya sarankan untuk melihat DefiantJS . Ini bukan XSLT setara untuk JSON, itu adalah XSLT untuk JSON. Bagian "Templating" dari dokumentasi termasuk contoh ini:

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

Saya benar-benar bosan dengan sejumlah besar mesin templating JavaScript di luar sana, dan semua templat HTML inline, gaya markup yang berbeda, dll., Dan memutuskan untuk membangun perpustakaan kecil yang memungkinkan pemformatan XSLT untuk memformat struktur data JSON. Bukan ilmu roket dengan cara apa pun - itu hanya JSON yang diuraikan ke XML dan kemudian diformat dengan dokumen XSLT. Ini juga cepat, tidak secepat mesin templat JavaScript di Chrome, tetapi di sebagian besar peramban lain setidaknya secepat mesin JS alternatif untuk struktur data yang lebih besar.

Björn
sumber
4

Saya menggunakan rute unta umarshal (xmljson) -> ke (xlst) -> marshal (xmljson). Cukup efisien (meski tidak 100% sempurna), tetapi sederhana, jika Anda sudah menggunakan Camel.

Ben Goldin
sumber
3

JSONiq adalah standar seperti itu dan Zorba merupakan implementasi C ++ open-source. JSONiq juga dapat dilihat sebagai XQuery dengan menambahkan JSON sebagai tipe data asli.

mb21
sumber
2

Yate ( https://github.com/pasaran/yate ) dirancang khusus setelah XSLT, fitur JPath (setara XPath alami untuk JS), dikompilasi dengan JavaScript dan memiliki riwayat penggunaan produksi yang cukup. Ini praktis tidak berdokumen, tetapi membaca sampel dan tes harus cukup.

K Lee
sumber
2

JSLT sangat dekat dengan JSON yang setara dengan XSLT. Ini adalah bahasa transformasi tempat Anda menulis bagian tetap dari output dalam sintaks JSON, lalu menyisipkan ekspresi untuk menghitung nilai yang ingin Anda sisipkan di templat.

Sebuah contoh:

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

Ini diterapkan di Jawa di atas Jackson.

Lars Marius Garshol
sumber
0

Tidak terlalu yakin ada kebutuhan untuk ini, dan bagi saya kurangnya alat menunjukkan kurangnya kebutuhan. JSON paling baik diproses sebagai objek (seperti yang dilakukan di JS), dan Anda biasanya menggunakan bahasa objek itu sendiri untuk melakukan transformasi (Java untuk objek Java yang dibuat dari JSON, sama untuk Perl, Python, Perl, c #, PHP dan sebagainya di). Hanya dengan penugasan normal (atau set, dapatkan), perulangan dan sebagainya.

Maksud saya, XSLT hanyalah bahasa lain, dan satu alasan diperlukan adalah bahwa XML bukan notasi objek dan dengan demikian objek bahasa pemrograman tidak cocok secara tepat (impedansi antara model xml hierarkis dan objek / objek / struct).

StaxMan
sumber
Setelah Facebook dikonversi dari XML ke Json, saya sangat membutuhkan alat seperti ini.
Joe Soul-bringer
Apa gunanya menurut Anda? Apakah itu dapat membuat konten JSON serupa dengan bagaimana Anda membuat tanggapan XML sebagai HTML? Atau sesuatu yang berbeda?
StaxMan
Saya bertanya-tanya betapa mudahnya untuk memanipulasi transformasi JSON dengan cara objek program (w / looping, bercabang sesuai kebutuhan, dll.) Vs menggunakan metode tipe XSLT, terutama dalam kasus mengubah objek JSON besar dan di mana beberapa data dalam sumber JSON digeser naik / turun beberapa node di target JSON (jadi bukan hanya salinan langsung dari struktur) dan mengatakan di mana simpul tertentu dalam sumber atau target JSON adalah bagian dari array objek dalam JSON dan JSON lainnya (sumber / target) tidak .
David
Kemudahan itu sangat subyektif, jadi saya curiga ada banyak hubungannya dengan apa yang sudah biasa.
StaxMan
Meskipun pasti ada kebutuhan untuk transformasi JSON, Anda benar itu sebagian besar dipenuhi oleh JS. :-) Tetapi apakah Anda melihat jq - prosesor JSON command-line yang ringan dan fleksibel ? Khusus untuk saat JS tidak tersedia. Saya akan mengatakan transformasi secara dramatis lebih mudah dan lebih intuitif, bahkan dari JS. misalnya untuk mengekstrak bidang namedan address, dan meletakkannya dalam array:[.name, .address]
13ren
0

Mengapa Anda tidak mengkonversi JSON ke XML menggunakan Mr. Data Coverter , mentransformasinya menggunakan XSLT dan kemudian mengubahnya kembali ke JSON menggunakan yang sama.

pengguna1058322
sumber
1
Itu bukan pilihan jika Anda ingin kode Anda melakukannya untuk Anda dengan kinerja yang baik.
orad
0

Untuk orat-oret kerja / bukti konsep pendekatan untuk memanfaatkan JavaScript murni bersama dengan pola akrab dan deklaratif di balik ekspresi pencocokan XSLT dan templat rekursif, lihat https://gist.github.com/brettz9/0e661b3093764f496e36

(Pendekatan serupa mungkin diambil untuk JSON.)

Perhatikan bahwa demo juga bergantung pada penutupan ekspresi JavaScript 1.8 untuk kenyamanan dalam mengekspresikan template di Firefox (setidaknya sampai bentuk pendek ES6 untuk metode dapat diterapkan).

Penafian: Ini adalah kode saya sendiri.

Brett Zamir
sumber
0

Saya menulis adaptor dom untuk kerangka kerja json berbasis jackson saya sejak lama. Ini menggunakan perpustakaan nu.xom. Pohon dom yang dihasilkan berfungsi dengan fasilitas xpath dan xslt java. Saya membuat beberapa pilihan implementasi yang cukup mudah. Misalnya simpul root selalu disebut "root", array masuk ke simpul ol dengan sub elemen li (seperti dalam html), dan segala sesuatu yang lain hanyalah sub node dengan nilai primitif atau node objek lain.

JsonXmlConverter.java

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

Jilles van Gurp
sumber
0

Satu pendekatan yang belum diberikan adalah menggunakan generator parser untuk membuat parser di XSLT yang mem-parsing JSON dan menghasilkan output XML.

Salah satu opsi yang banyak disebutkan di konferensi XML adalah generator parser ReX ( http://www.bottlecaps.de/rex/ ) - meskipun benar-benar tidak berdokumen di situs, resep tersedia untuk pencarian.

Tom Hillman
sumber
0

Dimungkinkan untuk menggunakan XSLT dengan JSON. Ayat 3 dari XPath (3.1) XSLT (3.0) dan XQuery (3.1) mendukung JSON dalam beberapa cara. Ini tampaknya tersedia dalam versi komersial Saxon, dan mungkin pada beberapa titik dimasukkan dalam versi HE. https://www.saxonica.com/html/documentation/functions/fn/parse-json.html

-

Apa yang saya harapkan dari solusi alternatif:

Saya ingin dapat memasukkan JSON untuk mengambil satu set data yang cocok, dan output JSON atau TEXT.

Akses properti sewenang-wenang dan evaluasi nilainya

Dukungan untuk logika kondisional

Saya ingin skrip transformasi eksternal dari alat, berbasis teks, dan lebih disukai bahasa yang umum digunakan.

Alternatif potensial?

Saya ingin tahu apakah SQL bisa menjadi alternatif yang cocok. https://docs.microsoft.com/en-us/sql/relational-databases/json/json-data-sql-server

Akan lebih baik jika alat alternatif dapat menangani JSON dan XML https://docs.microsoft.com/en-us/sql/relational-databases/xml/openxml-sql-server

Saya belum mencoba untuk mengkonversi skrip XSLT yang saya gunakan ke SQL, atau sepenuhnya mengevaluasi opsi ini, tetapi saya berharap untuk melihatnya lebih cepat. Hanya beberapa pemikiran sejauh ini.

Onceler
sumber