Apakah ada JSON yang setara dengan XQuery / XPath?

221

Saat mencari item dalam array dan hash JSON yang kompleks, seperti:

[
    { "id": 1, "name": "One", "objects": [
        { "id": 1, "name": "Response 1", "objects": [
            // etc.
        }]
    }
]

Apakah ada beberapa jenis bahasa query yang dapat saya gunakan untuk menemukan item in [0].objects where id = 3?

Naftuli Kay
sumber
tidak kecuali Anda membuatnya. Tinggalkan kueri ke server, dan gunakan REST untuk mendapatkan hanya data yang Anda butuhkan.
zzzzBov
5
+1 ide bagus. Akan menulis ini besok ...
2
Bukan XPath, tapi saya menemukan JLinq cukup bagus (yang membuat kode dibaca seperti in(...).where(...).select(...)): hugoware.net/Projects/jLinq .
pimvdb
4
Ini membuat frustrasi karena ada banyak perpustakaan di luar sana, tetapi tidak ada yang mendekati standar yang berlaku umum. Kami memiliki perpustakaan yang digunakan oleh pihak ke-3 sehingga kami harus menyediakan bahasa permintaan yang dikenal luas dan digunakan.
David Thielen
1
Tentu, Anda dapat menggunakan jsel - github.com/dragonworx/jsel - karena Anda memiliki variabel datayang berisi objek JSON Anda, Anda akan menulis: jsel(data).select("//*[@id=3]")dan itu akan mengembalikan objek yang berisi kunci id dengan 3.
Ali

Jawaban:

122

Yup, itu disebut JSONPath . Sumbernya sekarang ada di GitHub .

Ini juga terintegrasi ke dalam DOJO .

Mike Christensen
sumber
3
Jawaban Brian menunjukkan bahwa modul jsonQuery harus digunakan sebagai pengganti modul jsonPath di dojo.
hugomg
5
Seberapa solid ini? Dan saya tidak dapat menemukan versi Java atau C # yang merupakan kesepakatan bagi kami.
David Thielen
2
Situs yang tertaut di sini menyediakan Javascript dan PHP. Jika Anda memerlukan implementasi Java, ada satu di sini: code.google.com/p/json-path
Matthias Ronge
2
Saya harus menyebutkan bahwa JSONPath tidak didasarkan pada semantik formal XPath. JSONiq mungkin merupakan opsi yang lebih baik.
wcandillon
1
@Paramaeleon Itu sangat bagus. Omong -omong, proyek telah dimigrasikan ke GitHub . Mike mungkin ingin menambahkan ini ke jawabannya, karena orang-orang terus berkomentar tentang ini.
Franklin Yu
21

Saya pikir JSONQuery adalah superset dari JSONPath dan karenanya menggantikannya di dojo . Lalu ada juga RQL .

Dari dokumentasi Dojo:

JSONQuery adalah versi diperpanjang dari JSONPath dengan fitur tambahan untuk keamanan, kemudahan penggunaan, dan seperangkat alat query data yang komprehensif termasuk penyaringan, pencarian rekursif, pengurutan, pemetaan, pemilihan jangkauan, dan ekspresi fleksibel dengan perbandingan string wildcard dan berbagai operator.

JSONselect memiliki sudut pandang lain tentang pertanyaan (seperti pemilih CSS, bukan XPath) dan memiliki implementasi JavaScript .

Brian Clozel
sumber
4
Tautan JSONQuery github tampaknya sudah mati. JSONSelect juga memiliki versi JavaScript sekarang.
Henrik Aasted Sørensen
19

Alternatif lain yang saya ketahui adalah

  1. Spesifikasi JSONiq , yang menentukan dua subtipe bahasa: satu yang menyembunyikan detail XML dan menyediakan sintaks mirip JS, dan satu yang memperkaya sintaks XQuery dengan konstruktor JSON dan semacamnya. Zorba mengimplementasikan JSONiq.
  2. Corona , yang dibangun di atas MarkLogic menyediakan antarmuka REST untuk menyimpan, mengelola, dan mencari konten XML, JSON, Teks dan Biner.
  3. MarkLogic 6 dan yang lebih baru menyediakan antarmuka REST yang serupa dengan Corona di luar kotak.
  4. MarkLogic 8 dan yang lebih baru mendukung JSON di lingkungan XQuery dan sisi server JavaScript. Anda dapat menerapkan XPath di atasnya.

HTH.

grtjn
sumber
3
Sekarang ada implementasi JSONiq: Zorba 2.6 secara resmi mendukungnya.
Ghislain Fourny
Catatan: MarkLogic menyimpan JSON secara asli pada versi 8, dan memungkinkan menerapkan XPath secara langsung.
grtjn
18

Untuk meringkas beberapa opsi saat ini untuk melintasi / memfilter data JSON, dan memberikan beberapa contoh sintaksis ...

  • JSPath
    .automobiles{.maker === "Honda" && .year > 2009}.model

  • json: select () (lebih terinspirasi oleh penyeleksi CSS)
    .automobiles .maker:val("Honda") .model

  • JSONPath (terinspirasi lebih banyak oleh XPath)
    $.automobiles[?(@.maker='Honda')].model

Saya pikir JSPath terlihat paling bagus, jadi saya akan mencoba dan mengintegrasikannya dengan aplikasi AngularJS + CakePHP saya.

(Saya awalnya memposting jawaban ini di utas lain tetapi saya pikir ini akan berguna juga di sini.)

Simon Timur
sumber
Ringkasan dan contoh yang bagus, juga karena menyebutkan inspirasi yang ditemukan di penyeleksi CSS atau XPath.
Jochem Schulenklopper
13

Cobalah menggunakan JSPath

JSPath adalah bahasa khusus domain (DSL) yang memungkinkan Anda menavigasi dan menemukan data dalam dokumen JSON Anda. Menggunakan JSPath, Anda dapat memilih item JSON untuk mengambil data yang dikandungnya.

JSPath untuk JSON seperti XPath untuk XML.

Ini sangat dioptimalkan untuk Node.js dan browser modern.

dfilatov
sumber
9

XQuery dapat digunakan untuk permintaan JSON, asalkan prosesor menawarkan dukungan JSON. Ini adalah contoh sederhana bagaimana BaseX dapat digunakan untuk menemukan objek dengan "id" = 1:

json:parse('[
    { "id": 1, "name": "One", "objects": [
        { "id": 1, "name": "Response 1", "objects": [ "etc." ] }
    ]}
]')//value[.//id = 1]
Christian Grün
sumber
(6 tahun berlalu) Saxon akan menjalankan XQuery 3.1, yang menanyakan JSON. Pengalaman Saxon saya menggunakan file jar yang dijalankan oleh java. Ada modul simpul bernama saxon-java tetapi saya tidak yakin bagaimana cara kerjanya w / json. Dan ada hal baru lainnya dari Saxonica yang disebut Saxon-JS.
charles ross
9

Apakah ada semacam bahasa permintaan ...

JQ mendefinisikan J SON q bahasa uery yang sangat mirip dengan JSONPath - melihat https://github.com/stedolan/jq/wiki/For-JSONPath-users

... [yang] dapat saya gunakan untuk menemukan item dalam [0]. objek di mana id = 3?

Saya akan menganggap ini berarti: menemukan semua objek JSON di bawah kunci yang ditentukan dengan id == 3, di mana pun objek itu berada. Permintaan jq yang sesuai adalah:

.[0].objects | .. | objects | select(.id==3)

dimana "|" adalah pipa-operator (seperti dalam pipa shell perintah), dan di mana segmen ".. | objek" sesuai dengan "di mana pun objek mungkin".

Dasar-dasar jq sebagian besar jelas atau intuitif atau setidaknya cukup sederhana, dan sebagian besar sisanya mudah untuk diambil jika Anda sama sekali akrab dengan pipa shell perintah. FAQ jq memiliki petunjuk untuk tutorial dan sejenisnya.

jq juga seperti SQL yang mendukung operasi CRUD, meskipun prosesor jq tidak pernah menimpa inputnya. jq juga dapat menangani stream entitas JSON.

Dua kriteria lain yang mungkin ingin Anda pertimbangkan dalam menilai bahasa query berorientasi JSON adalah:

  • apakah itu mendukung ekspresi reguler? (jq 1.5 memiliki dukungan komprehensif untuk PCRE regex)
  • apakah sudah selesai Turing? (ya)
puncak
sumber
8

Defiant.js juga terlihat sangat keren, inilah contoh sederhana:

var obj = {
        "car": [
            {"id": 10, "color": "silver", "name": "Volvo"},
            {"id": 11, "color": "red",    "name": "Saab"},
            {"id": 12, "color": "red",    "name": "Peugeot"},
            {"id": 13, "color": "yellow", "name": "Porsche"}
        ],
        "bike": [
            {"id": 20, "color": "black", "name": "Cannondale"},
            {"id": 21, "color": "red",   "name": "Shimano"}
        ]
    },
    search = JSON.search(obj, '//car[color="yellow"]/name');

console.log( search );
// ["Porsche"]

var reds = JSON.search(obj, '//*[color="red"]');

for (var i=0; i<reds.length; i++) {
    console.log( reds[i].name );
}
// Saab
// Peugeot
// Shimano
Epoc
sumber
Sayangnya, tidak diterbitkan pada npm saat ini dan memerlukan instalasi manual ...
Andrew Mao
7

Jsel luar biasa dan didasarkan pada mesin XPath nyata. Ini memungkinkan Anda untuk membuat ekspresi XPath untuk menemukan semua jenis data JavaScript, bukan hanya objek (string juga).

Anda dapat membuat skema dan pemetaan khusus untuk memberi Anda kontrol penuh atas bagaimana data Anda dapat dilewati oleh mesin XPath. Skema adalah cara mendefinisikan bagaimana elemen, anak-anak, atribut, dan nilai simpul didefinisikan dalam data Anda. Kemudian Anda dapat membuat ekspresi Anda sendiri yang sesuai.

Mengingat Anda memiliki variabel yang dipanggil datayang berisi JSON dari pertanyaan, Anda bisa menggunakan jsel untuk menulis:

jsel(data).select("//*[@id=3]")

Ini akan mengembalikan simpul apa pun dengan idatribut 3. Atribut adalah nilai primitif (string, angka, tanggal, regex) apa pun dalam suatu objek.

Ali
sumber
6

ObjectPath adalah bahasa query yang mirip dengan XPath atau JSONPath, tetapi jauh lebih kuat berkat perhitungan aritmatika tertanam, mekanisme perbandingan, dan fungsi bawaan. Lihat sintaks:

Temukan di toko semua sepatu warna merah dan harga kurang dari 50

$ .. sepatu. * [warna "merah" dan harga <50]

Ela Bednarek
sumber
Saya suka contoh pertama di situs web dan itu bagus bahwa ObjectPath dapat dijalankan dalam mode berinteraksi, seperti shell, tapi apa yang saya cari adalah menggunakan ObjectPath dalam skrip Python. Bisakah Anda mengarahkan saya ke contoh yang menunjukkan cara menggunakan ObjectPath sebagai perpustakaan? Saya tidak dapat menemukan hal seperti itu di situs web.
piokuc
Silakan lihat bagian tentang penggunaan Python di github . Kami akan menambahkan ini ke situs web - memang sulit ditemukan saat ini. Jika Anda memerlukan bantuan lebih lanjut, Anda dapat memposting pertanyaan di grup google .
Ela Bednarek
Terima kasih, Ela, contoh yang ditambahkan pada halaman github adalah persis apa yang dibutuhkan.
piokuc
4

@Naftule - dengan "defiant.js", dimungkinkan untuk menanyakan struktur JSON dengan ekspresi XPath. Periksa evaluator ini untuk mengetahui cara kerjanya:

http://www.defiantjs.com/#xpath_evaluator

Tidak seperti JSONPath, "defiant.js" memberikan dukungan skala penuh dari sintaks kueri - XPath pada struktur JSON.

Kode sumber defiant.js dapat ditemukan di sini:
https://github.com/hbi99/defiant.js

Hakan Bilgin
sumber
3

JMESPath tampaknya sangat populer akhir-akhir ini (pada tahun 2020) dan membahas sejumlah masalah dengan JSONPath. Ini tersedia untuk banyak bahasa.

jlh
sumber
1

Jika Anda seperti saya dan Anda hanya ingin melakukan pencarian berbasis path, tetapi tidak peduli tentang XPath nyata, lodash _.get()dapat bekerja. Contoh dari lodash docs:

var object = { 'a': [{ 'b': { 'c': 3 } }] };

_.get(object, 'a[0].b.c');
// → 3

_.get(object, ['a', '0', 'b', 'c']);
// → 3

_.get(object, 'a.b.c', 'default');
// → 'default'
Adittes
sumber
Sayangnya fungsi itu hanya dapat mengembalikan satu hasil, tidak mendukung pengambilan array item yang cocok, yang mana perpustakaan lain bersinar.
Simon East