Saya ingin melintasi pohon objek JSON, tetapi tidak dapat menemukan perpustakaan untuk itu. Tampaknya tidak sulit tetapi rasanya seperti menciptakan kembali roda.
Dalam XML ada begitu banyak tutorial yang menunjukkan cara melintasi pohon XML dengan DOM :(
javascript
json
Patsy Issa
sumber
sumber
Jawaban:
Jika Anda berpikir jQuery agak berlebihan untuk tugas primitif seperti itu, Anda bisa melakukan sesuatu seperti itu:
sumber
this
nilai dalam fungsi target, sedangkano
harus menjadi parameter pertama ke fungsi. Mengaturnya kethis
(yang akan menjaditraverse
fungsi) agak aneh, tapi itu tidak sepertiprocess
menggunakanthis
referensi. Itu bisa saja nol./*jshint validthis: true */
atasfunc.apply(this,[i,o[i]]);
untuk menghindari kesalahan yangW040: Possible strict violation.
disebabkan oleh penggunaanthis
traverse
fungsi yang melacak kedalaman. Saat memanggil secara rekursif, tambahkan 1 ke level saat ini.Objek JSON hanyalah objek Javascript. Itulah sebenarnya singkatan JSON: JavaScript Object Notation. Jadi Anda akan melintasi objek JSON namun Anda akan memilih untuk "melintasi" objek Javascript secara umum.
Dalam ES2017 Anda akan melakukan:
Anda selalu dapat menulis fungsi untuk turun secara rekursif ke objek:
Ini harus menjadi titik awal yang baik. Saya sangat merekomendasikan menggunakan metode javascript modern untuk hal-hal seperti itu, karena mereka membuat penulisan kode seperti itu jauh lebih mudah.
sumber
function traverse(jsonObj) { if(jsonObj && typeof jsonObj == "object" ) { ...
sumber
much better
?!!o[i] && typeof o[i] == 'object'
Ada perpustakaan baru untuk melintasi data JSON dengan JavaScript yang mendukung banyak kasus penggunaan yang berbeda.
https://npmjs.org/package/traverse
https://github.com/substack/js-traverse
Ini bekerja dengan semua jenis objek JavaScript. Bahkan mendeteksi siklus.
Ini menyediakan jalur dari setiap node juga.
sumber
Tergantung pada apa yang ingin Anda lakukan. Berikut adalah contoh melintasi pohon objek JavaScript, mencetak kunci dan nilai saat berjalan:
sumber
Jika Anda melintasi string JSON yang sebenarnya, maka Anda dapat menggunakan fungsi reviver.
Saat melintasi objek:
sumber
EDIT : Semua contoh di bawah dalam jawaban ini telah diedit untuk menyertakan variabel jalur baru yang dihasilkan dari iterator sesuai permintaan @ supersan . Variabel path adalah array string di mana setiap string dalam array mewakili setiap kunci yang diakses untuk mendapatkan nilai iterasi yang dihasilkan dari objek sumber asli. Variabel path dapat dimasukkan ke dalam get function / method lodash . Atau Anda dapat menulis versi get lodash Anda sendiri yang hanya menangani array seperti:
EDIT : Jawaban yang diedit ini memecahkan traversal infinite looping.
Menghentikan Pesky Infinite Object Traversals
Jawaban yang diedit ini masih memberikan salah satu manfaat tambahan dari jawaban asli saya yang memungkinkan Anda untuk menggunakan fungsi generator yang disediakan untuk menggunakan antarmuka yang lebih bersih dan sederhana yang dapat diubah (pikirkan menggunakan
for of
loop seperti difor(var a of b)
manab
iterable dana
merupakan elemen iterable ). Dengan menggunakan fungsi generator dan menjadi api yang lebih sederhana, ia juga membantu penggunaan kembali kode dengan membuatnya jadi Anda tidak perlu mengulangi logika iterasi di mana pun Anda ingin mengulangi secara mendalam pada properti objek dan juga memungkinkan untukbreak
keluar dari loop jika Anda ingin menghentikan iterasi lebih awal.Satu hal yang saya perhatikan yang belum diatasi dan yang tidak ada dalam jawaban asli saya adalah bahwa Anda harus berhati-hati melintasi objek yang sewenang-wenang (yaitu set "acak"), karena objek JavaScript dapat merujuk sendiri. Ini menciptakan peluang untuk memiliki traverse looping tanpa batas. Namun data JSON yang tidak dimodifikasi tidak dapat menjadi referensi sendiri, jadi jika Anda menggunakan subset objek JS ini, Anda tidak perlu khawatir tentang perulangan perulangan tak terbatas dan Anda dapat merujuk ke jawaban asli saya atau jawaban lain. Berikut ini adalah contoh dari traversal tanpa akhir (perhatikan itu bukan sepotong kode yang bisa dijalankan, karena jika tidak maka akan crash tab browser Anda).
Juga dalam objek generator dalam contoh saya yang diedit saya memilih untuk menggunakan
Object.keys
alih-alihfor in
hanya kunci non-prototipe pada objek. Anda dapat menukar ini sendiri jika Anda ingin kunci prototipe disertakan. Lihat bagian jawaban asli saya di bawah ini untuk implementasi denganObject.keys
danfor in
.Lebih buruk - Ini akan infinite loop pada objek referensial diri:
Untuk menyelamatkan diri Anda dari ini, Anda dapat menambahkan satu set dalam penutupan, sehingga ketika fungsi pertama kali dipanggil itu mulai membangun memori objek yang telah dilihat dan tidak melanjutkan iterasi setelah menemukan objek yang sudah terlihat. Cuplikan kode di bawah melakukan hal itu dan dengan demikian menangani kasus pengulangan yang tak terbatas.
Lebih baik - Ini tidak akan infinite loop pada objek referensial diri:
Jawaban Asli
Untuk cara yang lebih baru untuk melakukannya jika Anda tidak keberatan menjatuhkan IE dan terutama mendukung lebih banyak browser saat ini (periksa tabel ES6 kangax untuk kompatibilitas). Anda dapat menggunakan generator es2015 untuk ini. Saya telah memperbarui jawaban TheHippo. Tentu saja jika Anda benar-benar menginginkan dukungan IE Anda dapat menggunakan babel JavaScript transpiler.
Jika Anda hanya ingin memiliki properti enumerable (pada dasarnya properti rantai non-prototipe), Anda dapat mengubahnya untuk beralih menggunakan
Object.keys
danfor...of
loop sebagai gantinya:sumber
Saya ingin menggunakan solusi sempurna dari @TheHippo dalam fungsi anonim, tanpa menggunakan proses dan fungsi pemicu. Berikut ini bekerja untuk saya, berbagi untuk programmer pemula seperti saya.
sumber
Sebagian besar mesin Javascript tidak mengoptimalkan rekursi ekor (ini mungkin bukan masalah jika JSON Anda tidak bersarang secara mendalam), tetapi saya biasanya melakukan kesalahan dengan berhati-hati dan melakukan iterasi sebagai gantinya, misalnya
sumber
Skrip saya:
Masukkan JSON:
Panggilan fungsi:
Output sesuai Kebutuhan saya:
sumber
sumber
Solusi terbaik bagi saya adalah sebagai berikut:
sederhana dan tanpa menggunakan kerangka apa pun
sumber
Anda bisa mendapatkan semua kunci / nilai dan mempertahankan hierarki dengan ini
Ini adalah modifikasi pada ( https://stackoverflow.com/a/25063574/1484447 )
sumber
sumber
Saya telah membuat pustaka untuk melintasi dan mengedit objek JS yang bersarang. Lihat API di sini: https://github.com/dominik791
Anda juga dapat bermain dengan perpustakaan secara interaktif menggunakan aplikasi demo: https://dominik791.github.io/obj-traverse-demo/
Contoh penggunaan: Anda harus selalu memiliki objek root yang merupakan parameter pertama dari setiap metode:
Parameter kedua selalu nama properti yang menyimpan objek bersarang. Dalam kasus di atas akan menjadi
'children'
.Parameter ketiga adalah objek yang Anda gunakan untuk menemukan objek / objek yang ingin Anda temukan / ubah / hapus. Misalnya jika Anda mencari objek dengan id sama dengan 1, maka Anda akan lulus
{ id: 1}
sebagai parameter ketiga.Dan kamu bisa:
findFirst(rootObj, 'children', { id: 1 })
untuk menemukan objek pertama denganid === 1
findAll(rootObj, 'children', { id: 1 })
untuk menemukan semua objek denganid === 1
findAndDeleteFirst(rootObj, 'children', { id: 1 })
untuk menghapus objek yang cocok pertamafindAndDeleteAll(rootObj, 'children', { id: 1 })
untuk menghapus semua objek yang cocokreplacementObj
digunakan sebagai parameter terakhir dalam dua metode terakhir:findAndModifyFirst(rootObj, 'children', { id: 1 }, { id: 2, name: 'newObj'})
untuk mengubah objek yang ditemukan pertama denganid === 1
ke{ id: 2, name: 'newObj'}
findAndModifyAll(rootObj, 'children', { id: 1 }, { id: 2, name: 'newObj'})
untuk mengubah semua objek denganid === 1
ke{ id: 2, name: 'newObj'}
sumber