Bagaimana saya bisa mengakses dan memproses objek, array, atau JSON yang bersarang?

875

Saya memiliki struktur data bersarang yang berisi objek dan array. Bagaimana saya bisa mengekstrak informasi, yaitu mengakses nilai (atau kunci) tertentu atau beberapa?

Sebagai contoh:

var data = {
    code: 42,
    items: [{
        id: 1,
        name: 'foo'
    }, {
        id: 2,
        name: 'bar'
    }]
};

Bagaimana saya bisa mengakses nameitem kedua di items?

Felix Kling
sumber
22
@ Marscel: Itu harus dibaca sebagai "Saya memiliki struktur data bersarang data atau JSON, bagaimana saya bisa mengakses nilai tertentu?". Saya tahu bedanya, tetapi banyak orang tidak dan mungkin mencari "JSON" daripada "objek". Banyak pertanyaan sebenarnya dalam bentuk "bagaimana saya bisa mengakses X di JSON ini". Satu-satunya tempat saya menyebutkan JSON dalam jawaban saya adalah tempat saya menjelaskan apa itu JSON. Jika Anda memiliki saran bagaimana mengkomunikasikan hal ini dengan cara yang lebih baik, saya mendengar semuanya.
Felix Kling
kemungkinan duplikat dari JSON ditemukan dalam JavaScript
Travis J

Jawaban:

1160

Persiapan

JavaScript hanya memiliki satu tipe data yang dapat berisi banyak nilai: Objek . Sebuah Array adalah bentuk khusus dari objek.

(Biasa) Objek memiliki bentuk

{key: value, key: value, ...}

Array memiliki formulir

[value, value, ...]

Baik array dan objek memperlihatkan key -> valuestruktur. Kunci dalam array harus berupa angka, sedangkan string apa pun dapat digunakan sebagai kunci dalam objek. Pasangan kunci-nilai juga disebut "properti" .

Properti dapat diakses menggunakan notasi titik

const value = obj.someProperty;

atau notasi braket , jika nama properti tidak akan menjadi nama pengidentifikasi JavaScript yang valid [spec] , atau namanya adalah nilai dari variabel:

// the space is not a valid character in identifier names
const value = obj["some Property"];

// property name as variable
const name = "some Property";
const value = obj[name];

Karena alasan itu, elemen array hanya dapat diakses menggunakan notasi braket:

const value = arr[5]; // arr.5 would be a syntax error

// property name / index as variable
const x = 5;
const value = arr[x];

Tunggu ... bagaimana dengan JSON?

JSON adalah representasi data tekstual, seperti XML, YAML, CSV, dan lainnya. Untuk bekerja dengan data tersebut, pertama-tama harus dikonversi ke tipe data JavaScript, yaitu array dan objek (dan cara bekerja dengan itu baru saja dijelaskan). Bagaimana cara menguraikan JSON dijelaskan dalam pertanyaan Parse JSON dalam JavaScript? .

Bahan bacaan lebih lanjut

Cara mengakses array dan objek adalah pengetahuan JavaScript yang mendasar dan oleh karena itu disarankan untuk membaca Panduan JavaScript MDN , terutama bagian-bagiannya



Mengakses struktur data bersarang

Struktur data bersarang adalah array atau objek yang merujuk ke array atau objek lain, yaitu nilainya adalah array atau objek. Struktur tersebut dapat diakses dengan menerapkan notasi titik atau braket secara berurutan.

Berikut ini sebuah contoh:

const data = {
    code: 42,
    items: [{
        id: 1,
        name: 'foo'
    }, {
        id: 2,
        name: 'bar'
    }]
};

Mari kita asumsikan kita ingin mengakses nameitem kedua.

Inilah cara kita melakukannya langkah demi langkah:

Seperti yang dapat kita lihat dataadalah objek, maka kita dapat mengakses propertinya menggunakan notasi titik. The itemsproperti diakses sebagai berikut:

data.items

Nilainya adalah sebuah array, untuk mengakses elemen keduanya, kita harus menggunakan notasi braket:

data.items[1]

Nilai ini adalah objek dan kami menggunakan notasi titik lagi untuk mengakses nameproperti. Jadi kami akhirnya mendapatkan:

const item_name = data.items[1].name;

Atau, kami dapat menggunakan notasi braket untuk salah satu properti, terutama jika nama tersebut mengandung karakter yang membuatnya tidak valid untuk penggunaan notasi titik:

const item_name = data['items'][1]['name'];

Saya mencoba mengakses properti tetapi saya hanya mendapatkan undefinedkembali?

Sebagian besar waktu ketika Anda mendapatkan undefined, objek / array tidak memiliki properti dengan nama itu.

const foo = {bar: {baz: 42}};
console.log(foo.baz); // undefined

Gunakan console.logatau console.dirdan periksa struktur objek / array. Properti yang Anda coba akses mungkin sebenarnya ditentukan pada objek / array bersarang.

console.log(foo.bar.baz); // 42

Bagaimana jika nama properti dinamis dan saya tidak mengetahuinya sebelumnya?

Jika nama properti tidak diketahui atau kami ingin mengakses semua properti dari suatu objek / elemen array, kita dapat menggunakan loop for...in [MDN] untuk objek dan loop for [MDN] untuk array untuk beralih ke semua properti / elemen.

Benda

Untuk mengulangi semua properti dari data, kita dapat beralih di atas objek seperti:

for (const prop in data) {
    // `prop` contains the name of each property, i.e. `'code'` or `'items'`
    // consequently, `data[prop]` refers to the value of each property, i.e.
    // either `42` or the array
}

Bergantung pada dari mana objek itu berasal (dan apa yang ingin Anda lakukan), Anda mungkin harus menguji di setiap iterasi apakah properti itu benar-benar properti objek, atau properti warisan. Anda dapat melakukan ini dengan Object#hasOwnProperty [MDN] .

Sebagai alternatif for...indengan hasOwnProperty, Anda dapat menggunakan Object.keys [MDN] untuk mendapatkan berbagai nama properti :

Object.keys(data).forEach(function(prop) {
  // `prop` is the property name
  // `data[prop]` is the property value
});

Array

Untuk beralih ke semua elemen data.items array , kami menggunakan forloop:

for(let i = 0, l = data.items.length; i < l; i++) {
    // `i` will take on the values `0`, `1`, `2`,..., i.e. in each iteration
    // we can access the next element in the array with `data.items[i]`, example:
    // 
    // var obj = data.items[i];
    // 
    // Since each element is an object (in our example),
    // we can now access the objects properties with `obj.id` and `obj.name`. 
    // We could also use `data.items[i].id`.
}

Kita juga bisa menggunakannya for...inuntuk beralih pada array, tetapi ada alasan mengapa ini harus dihindari: Mengapa 'untuk (item dalam daftar)' dengan array dianggap praktik yang buruk dalam JavaScript? .

Dengan meningkatnya dukungan browser dari ECMAScript 5, metode array forEach [MDN] juga menjadi alternatif yang menarik:

data.items.forEach(function(value, index, array) {
    // The callback is executed for each element in the array.
    // `value` is the element itself (equivalent to `array[index]`)
    // `index` will be the index of the element in the array
    // `array` is a reference to the array itself (i.e. `data.items` in this case)
}); 

Dalam lingkungan yang mendukung ES2015 (ES6), Anda juga dapat menggunakan loop [MDN] , yang tidak hanya berfungsi untuk array, tetapi untuk semua iterable :for...of

for (const item of data.items) {
   // `item` is the array element, **not** the index
}

Dalam setiap iterasi, for...ofsecara langsung memberi kita elemen iterable berikutnya, tidak ada "indeks" untuk diakses atau digunakan.


Bagaimana jika "kedalaman" struktur data tidak saya ketahui?

Selain kunci yang tidak dikenal, "kedalaman" dari struktur data (yaitu berapa banyak objek bersarang) yang dimilikinya, mungkin juga tidak diketahui. Cara mengakses properti yang sangat bersarang biasanya tergantung pada struktur data yang tepat.

Tetapi jika struktur data berisi pola berulang, misalnya representasi pohon biner, solusinya biasanya mencakup [Wikipedia] secara rekursif mengakses setiap tingkat struktur data.

Berikut adalah contoh untuk mendapatkan simpul daun pertama dari pohon biner:

function getLeaf(node) {
    if (node.leftChild) {
        return getLeaf(node.leftChild); // <- recursive call
    }
    else if (node.rightChild) {
        return getLeaf(node.rightChild); // <- recursive call
    }
    else { // node must be a leaf node
        return node;
    }
}

const first_leaf = getLeaf(root);

Cara yang lebih umum untuk mengakses struktur data bersarang dengan kunci dan kedalaman yang tidak dikenal adalah dengan menguji jenis nilai dan bertindak sesuai.

Berikut adalah contoh yang menambahkan semua nilai primitif di dalam struktur data bersarang ke dalam array (dengan asumsi itu tidak mengandung fungsi apa pun). Jika kita menemukan objek (atau array), kita cukup memanggil toArraylagi pada nilai itu (panggilan rekursif).

function toArray(obj) {
    const result = [];
    for (const prop in obj) {
        const value = obj[prop];
        if (typeof value === 'object') {
            result.push(toArray(value)); // <- recursive call
        }
        else {
            result.push(value);
        }
    }
    return result;
}



Pembantu

Karena struktur objek atau array yang kompleks belum tentu jelas, kita dapat memeriksa nilai pada setiap langkah untuk memutuskan bagaimana bergerak lebih jauh. console.log [MDN] dan console.dir [MDN] membantu kami melakukan ini. Misalnya (output dari konsol Chrome):

> console.log(data.items)
 [ Object, Object ]

Di sini kita melihat bahwa itu data.itemsadalah array dengan dua elemen yang keduanya objek. Di konsol Chrome objek bahkan dapat diperluas dan diperiksa segera.

> console.log(data.items[1])
  Object
     id: 2
     name: "bar"
     __proto__: Object

Ini memberi tahu kita bahwa itu data.items[1]adalah objek, dan setelah meluaskannya kita melihat bahwa ia memiliki tiga properti id,, namedan __proto__. Yang terakhir adalah properti internal yang digunakan untuk rantai prototipe objek. Rantai prototipe dan warisan tidak termasuk dalam cakupan untuk jawaban ini.

Felix Kling
sumber
3
Beberapa hal yang terhubung di sini benar-benar bertanya bagaimana melakukan ini di jQuery, yang mana harus adil memang menyederhanakan 1 atau 2 hal di sini. Tidak yakin apakah akan membuat ini lebih dari sebuah megapost atau menjawabnya secara terpisah - dasar-dasar yang dibahas di sini tentang objek apa yang biasanya merupakan array yang diminta ....
Chris Moschini
1
@ felix-kling Satu hal ... dengan objek bersarang, seperti let object = {a: 1, b: 2, c: { a: 3, b: 4 }};, ini mengembalikan array yang berisi array untuk setiap objek bersarang, dalam hal ini [ 1, 2, [ 3, 4 ] ]Bukankah lebih baik menggunakan concat dalam panggilan rekursif alih-alih mendorong? (membutuhkan hasil yang dapat diubah)
ElFitz
3
Ini adalah jawaban paling mendalam yang pernah saya lihat di Stack Overflow - dan itu menjawab pertanyaan saya! Terima kasih!
William Jones
halaman yang satu ini membuat saya belajar perbedaan antara ARRAY dan OBJ
4ni5
76

Anda dapat mengaksesnya dengan cara ini

data.items[1].name

atau

data["items"][1]["name"]

Kedua cara itu sama.

vitmalina
sumber
Ya tetapi Anda tidak dapat melakukan data ["item"] 1.name
neaumusic
5
Pertama jauh lebih intuitif, mudah dibaca dan lebih pendek;) Saya lebih suka menggunakan sintaks properti braket hanya ketika nama properti variabel.
DanteTheSmith
35

Jika Anda mencoba mengakses itemstruktur contoh dengan idatau name, tanpa mengetahui posisinya di dalam array, cara termudah untuk melakukannya adalah dengan menggunakan pustaka underscore.js :

var data = {
    code: 42,
    items: [{
        id: 1,
        name: 'foo'
    }, {
        id: 2,
        name: 'bar'
    }]
};

_.find(data.items, function(item) {
  return item.id === 2;
});
// Object {id: 2, name: "bar"}

Dari pengalaman saya, menggunakan fungsi urutan yang lebih tinggi daripada foratau for..inloop menghasilkan kode yang lebih mudah untuk dipikirkan, dan karenanya lebih dapat dipertahankan.

Hanya 2 sen saya.

prinsip holografik
sumber
29

Objek dan array memiliki banyak metode bawaan yang dapat membantu Anda dalam memproses data.

Catatan: dalam banyak contoh saya menggunakan fungsi panah . Mereka mirip dengan ekspresi fungsi , tetapi mereka mengikat thisnilai secara leksikal.

Object.keys(), Object.values()(ES 2017) dan Object.entries()(ES 2017)

Object.keys()mengembalikan array kunci objek, Object.values()mengembalikan array nilai objek, dan Object.entries()mengembalikan array kunci objek dan nilai yang sesuai dalam suatu format [key, value].

const obj = {
  a: 1
 ,b: 2
 ,c: 3
}

console.log(Object.keys(obj)) // ['a', 'b', 'c']
console.log(Object.values(obj)) // [1, 2, 3]
console.log(Object.entries(obj)) // [['a', 1], ['b', 2], ['c', 3]]

Object.entries() dengan for-of loop dan penugasan penugasan

const obj = {
  a: 1
 ,b: 2
 ,c: 3
}

for (const [key, value] of Object.entries(obj)) {
  console.log(`key: ${key}, value: ${value}`)
}

Sangat mudah untuk mengulangi hasil Object.entries()dengan for-of loop dan tugas penataan .

For-of loop memungkinkan Anda mengulangi elemen array. Sintaksnya adalah for (const element of array)(kita dapat mengganti constdengan varatau let, tetapi lebih baik digunakan constjika kita tidak ingin memodifikasi element).

Merusak penugasan memungkinkan Anda mengekstrak nilai dari array atau objek dan menetapkannya ke variabel. Dalam hal ini const [key, value]berarti bahwa alih-alih menugaskan [key, value]array element, kami menetapkan elemen pertama array itu keydan elemen kedua value. Ini setara dengan ini:

for (const element of Object.entries(obj)) {
  const key = element[0]
       ,value = element[1]
}

Seperti yang Anda lihat, perusakan membuat ini lebih sederhana.

Array.prototype.every() dan Array.prototype.some()

The every()kembali metode truejika fungsi callback pengembalian yang ditentukan trueuntuk setiap elemen array. The some()kembali metode truejika fungsi callback tertentu kembali trueuntuk beberapa (setidaknya satu) elemen.

const arr = [1, 2, 3]

// true, because every element is greater than 0
console.log(arr.every(x => x > 0))
// false, because 3^2 is greater than 5
console.log(arr.every(x => Math.pow(x, 2) < 5))
// true, because 2 is even (the remainder from dividing by 2 is 0)
console.log(arr.some(x => x % 2 === 0))
// false, because none of the elements is equal to 5
console.log(arr.some(x => x === 5))

Array.prototype.find() dan Array.prototype.filter()

The find()metode mengembalikan pertama unsur yang memenuhi fungsi callback yang disediakan. The filter()Metode mengembalikan array semua elemen yang memenuhi fungsi callback yang disediakan.

const arr = [1, 2, 3]

// 2, because 2^2 !== 2
console.log(arr.find(x => x !== Math.pow(x, 2)))
// 1, because it's the first element
console.log(arr.find(x => true))
// undefined, because none of the elements equals 7
console.log(arr.find(x => x === 7))

// [2, 3], because these elements are greater than 1
console.log(arr.filter(x => x > 1))
// [1, 2, 3], because the function returns true for all elements
console.log(arr.filter(x => true))
// [], because none of the elements equals neither 6 nor 7
console.log(arr.filter(x => x === 6 || x === 7))

Array.prototype.map()

The map()Metode mengembalikan array dengan hasil memanggil fungsi callback disediakan di elemen array.

const arr = [1, 2, 3]

console.log(arr.map(x => x + 1)) // [2, 3, 4]
console.log(arr.map(x => String.fromCharCode(96 + x))) // ['a', 'b', 'c']
console.log(arr.map(x => x)) // [1, 2, 3] (no-op)
console.log(arr.map(x => Math.pow(x, 2))) // [1, 4, 9]
console.log(arr.map(String)) // ['1', '2', '3']

Array.prototype.reduce()

The reduce()Metode mengurangi array untuk nilai tunggal dengan memanggil fungsi callback yang disediakan dengan dua elemen.

const arr = [1, 2, 3]

// Sum of array elements.
console.log(arr.reduce((a, b) => a + b)) // 6
// The largest number in the array.
console.log(arr.reduce((a, b) => a > b ? a : b)) // 3

The reduce()Metode mengambil parameter opsional kedua, yang merupakan nilai awal. Ini berguna ketika array yang Anda panggil reduce()dapat memiliki nol atau satu elemen. Misalnya, jika kita ingin membuat fungsi sum()yang menggunakan array sebagai argumen dan mengembalikan jumlah semua elemen, kita bisa menulisnya seperti itu:

const sum = arr => arr.reduce((a, b) => a + b, 0)

console.log(sum([]))     // 0
console.log(sum([4]))    // 4
console.log(sum([2, 5])) // 7

Michał Perłakowski
sumber
Ini jawaban favorit saya. Anda juga bisa menambahkan contoh untuk loop hanya data bersarang expecific, sepertiObject.keys(data["items"]).forEach(function(key) { console.log(data["items"][key].id); console.log(data["items"][key].name); });
SilverSurfer
25

Kadang-kadang, mengakses objek bersarang menggunakan string dapat diinginkan. Pendekatan sederhana adalah tingkat pertama, misalnya

var obj = { hello: "world" };
var key = "hello";
alert(obj[key]);//world

Tapi ini sering tidak terjadi dengan json kompleks. Ketika json menjadi lebih kompleks, pendekatan untuk menemukan nilai-nilai di dalam json juga menjadi kompleks. Pendekatan rekursif untuk menavigasi json adalah yang terbaik, dan bagaimana rekursi itu dimanfaatkan akan tergantung pada jenis data yang dicari. Jika ada pernyataan kondisional yang terlibat, pencarian json bisa menjadi alat yang baik untuk digunakan.

Jika properti yang diakses sudah diketahui, tetapi jalurnya kompleks, misalnya dalam objek ini

var obj = {
 arr: [
    { id: 1, name: "larry" },    
    { id: 2, name: "curly" },
    { id: 3, name: "moe" }
 ]
};

Dan Anda tahu Anda ingin mendapatkan hasil pertama dari array di objek, mungkin Anda ingin menggunakannya

var moe = obj["arr[0].name"];

Namun, itu akan menyebabkan pengecualian karena tidak ada properti objek dengan nama itu. Solusi untuk dapat menggunakan ini adalah dengan meratakan aspek pohon objek. Ini dapat dilakukan secara rekursif.

function flatten(obj){
 var root = {};
 (function tree(obj, index){
   var suffix = toString.call(obj) == "[object Array]" ? "]" : "";
   for(var key in obj){
    if(!obj.hasOwnProperty(key))continue;
    root[index+key+suffix] = obj[key];
    if( toString.call(obj[key]) == "[object Array]" )tree(obj[key],index+key+suffix+"[");
    if( toString.call(obj[key]) == "[object Object]" )tree(obj[key],index+key+suffix+".");   
   }
 })(obj,"");
 return root;
}

Sekarang, objek yang kompleks dapat diratakan

var obj = previous definition;
var flat = flatten(obj);
var moe = flat["arr[0].name"];//moe

Ini adalah salah jsFiddle Demosatu pendekatan yang digunakan.

Travis J
sumber
WTH yang ingin Anda gunakan obj["arr[0].name"]bukan obj.arr[0].name? Anda tidak perlu / ingin berurusan dengan objek yang rata kecuali untuk serialisasi.
Bergi
@Bergi - Saya melihat pertanyaan ini secara umum, dan karena ini digunakan secara kanonik, saya mengirimkan jawaban untuk versi itu. Jika itu bisa dihindari itu jauh lebih cepat untuk menggunakan obj.arr [0] .name, tetapi kadang-kadang orang ingin melewati pengakses string di sekitar dan ini adalah contoh dari melakukan itu.
Travis J
Urgh. Namun, hampir tidak ada alasan untuk meratakan objek lengkap hanya dengan menggunakan jalur string tunggal, Anda bisa menguraikannya dan melakukan pencarian dinamis.
Bergi
14

Pertanyaan ini cukup lama, sehingga merupakan pembaruan kontemporer. Dengan dimulainya ES2015 ada alternatif untuk mendapatkan data yang Anda butuhkan. Sekarang ada fitur yang disebut destruksi objek untuk mengakses objek bersarang.

const data = {
  code: 42,
  items: [{
    id: 1,
    name: 'foo'
  }, {
    id: 2,
    name: 'bar'
  }]
};

const {
  items: [, {
    name: secondName
  }]
} = data;

console.log(secondName);

Contoh di atas membuat variabel yang dipanggil secondNamedari namekunci dari array yang disebut items, ,kata kesepian melewati objek pertama dalam array.

Khususnya mungkin berlebihan untuk contoh ini, karena akses array sederhana lebih mudah dibaca, tetapi berguna saat memecah objek secara umum.

Ini adalah pengantar yang sangat singkat untuk kasus penggunaan khusus Anda, perusakan dapat menjadi sintaks yang tidak biasa untuk digunakan pada awalnya. Saya akan merekomendasikan membaca dokumentasi Mozilla's Destructure Assignment untuk mempelajari lebih lanjut.

Alex KeySmith
sumber
13

Untuk mengakses atribut bersarang, Anda perlu menentukan namanya dan kemudian mencari melalui objek.

Jika Anda sudah tahu path yang tepat, maka Anda bisa membuat hardcode di skrip Anda seperti:

data['items'][1]['name']

ini juga bekerja -

data.items[1].name
data['items'][1].name
data.items[1]['name']

Ketika Anda tidak tahu nama persisnya sebelumnya, atau pengguna adalah orang yang memberikan nama untuk Anda. Maka pencarian secara dinamis melalui struktur data diperlukan. Beberapa menyarankan di sini bahwa pencarian dapat dilakukan menggunakan forloop, tetapi ada cara yang sangat sederhana untuk melintasi jalur menggunakan Array.reduce.

const data = { code: 42, items: [{ id: 1, name: 'foo' }, { id: 2, name: 'bar' }] }
const path = [ 'items', '1', 'name']
let result = path.reduce((a,v) => a[v], data)

Path adalah cara untuk mengatakan: Pertama ambil objek dengan kunci items, yang kebetulan berupa array. Kemudian ambil 1elemen -st (array indeks 0). Terakhir ambil objek dengan kunci namedalam elemen array itu, yang merupakan string bar.

Jika Anda memiliki jalan yang sangat panjang, Anda bahkan dapat menggunakan String.splituntuk mempermudah semua ini -

'items.1.name'.split('.').reduce((a,v) => a[v], data)

Ini hanyalah JavaScript biasa, tanpa menggunakan perpustakaan pihak ketiga seperti jQuery atau lodash.

Evgeny
sumber
13
var ourStorage = {


"desk":    {
    "drawer": "stapler"
  },
"cabinet": {
    "top drawer": { 
      "folder1": "a file",
      "folder2": "secrets"
    },
    "bottom drawer": "soda"
  }
};
ourStorage.cabinet["top drawer"].folder2; // Outputs -> "secrets"

atau

//parent.subParent.subsubParent["almost there"]["final property"]

Pada dasarnya, gunakan titik di antara setiap keturunan yang terungkap di bawahnya dan ketika Anda memiliki nama objek yang terbuat dari dua string, Anda harus menggunakan notasi ["Object Name"]. Kalau tidak, cukup satu titik saja sudah cukup;

Sumber: https://learn.freecodecamp.org/javascript-algorithms-and-data-structures/basic-javascript/accessing-nested-objects

untuk menambah ini, mengakses Array bersarang akan terjadi seperti:

var ourPets = [
  {
    animalType: "cat",
    names: [
      "Meowzer",
      "Fluffy",
      "Kit-Cat"
    ]
  },
  {
    animalType: "dog",
    names: [
      "Spot",
      "Bowser",
      "Frankie"
    ]
  }
];
ourPets[0].names[1]; // Outputs "Fluffy"
ourPets[1].names[0]; // Outputs "Spot"

Sumber: https://learn.freecodecamp.org/javascript-algorithms-and-data-structures/basic-javascript/accessing-nested-arrays/

Dokumen lain yang lebih bermanfaat menggambarkan situasi di atas: https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Basics#Bracket_notation

Akses properti melalui dot walking: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Property_Accessors#Dot_notation

Johnny
sumber
Meskipun tautan ini dapat menjawab pertanyaan, lebih baik untuk memasukkan bagian-bagian penting dari jawaban di sini dan memberikan tautan untuk referensi. Jawaban hanya tautan dapat menjadi tidak valid jika halaman tertaut berubah. - Dari Ulasan
Robert
1
Saya mengedit posting. Semua orang berpikir cepat untuk memberikan rep yang buruk untuk itu. Lain kali saya akan menahan diri untuk tidak memberikan jawaban.
Johnny
1
@Riddick jangan menahan diri, pastikan Anda tidak hanya memposting tautan
reggaeguitar
12

Anda bisa menggunakan lodash _getfungsi:

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

_.get(object, 'a[0].b.c');
// => 3
Sergey
sumber
9

Menggunakan JSONPath akan menjadi salah satu solusi paling fleksibel jika Anda bersedia menyertakan perpustakaan: https://github.com/s3u/JSONPath (node ​​dan browser)

Untuk kasus penggunaan Anda, json path adalah:

$..items[1].name

begitu:

var secondName = jsonPath.eval(data, "$..items[1].name");
Andrejs
sumber
1
Menggunakan eval () bukanlah solusi yang baik. Sebaliknya fungsi kelas dapat digunakan.
pradeep gowda
8

Untuk jaga-jaga, siapa pun yang mengunjungi pertanyaan ini pada 2017 atau lebih baru dan mencari cara yang mudah diingat , berikut ini adalah posting blog yang rumit tentang Mengakses Objek Bersarang di JavaScript tanpa dikacaukan oleh

Tidak dapat membaca properti 'foo' dari kesalahan yang tidak terdefinisi

1. Pola akses objek bersarang Oliver Steele

Cara termudah dan terbersih adalah dengan menggunakan pola akses objek bersarang Oliver Steele

const name = ((user || {}).personalInfo || {}).name;

Dengan notasi ini, Anda tidak akan pernah bertemu

Tidak dapat membaca properti 'nama' yang tidak terdefinisi .

Anda pada dasarnya memeriksa apakah pengguna ada, jika tidak, Anda membuat objek kosong dengan cepat. Dengan cara ini, kunci level berikutnya akan selalu diakses dari objek yang ada atau objek kosong , tetapi tidak pernah dari yang tidak ditentukan.

2. Akses Objek Bersarang Menggunakan Array Reduce

Untuk dapat mengakses array bersarang, Anda dapat menulis util pengurangan array Anda sendiri.

const getNestedObject = (nestedObj, pathArr) => {
    return pathArr.reduce((obj, key) =>
        (obj && obj[key] !== 'undefined') ? obj[key] : undefined, nestedObj);
}

// pass in your object structure as array elements
const name = getNestedObject(user, ['personalInfo', 'name']);

// to access nested array, just pass in array index as an element the path array.
const city = getNestedObject(user, ['personalInfo', 'addresses', 0, 'city']);
// this will return the city from the first address item.

Ada juga jenis penanganan perpustakaan typy yang sangat baik yang melakukan semua ini untuk Anda.

Dinesh Pandiyan
sumber
3
Pertanyaan ini terutama tentang akses properti yang ada. Sudah ada pertanyaan tentang apa yang Anda maksudkan (dan sudah termasuk sebagian besar solusi Anda): Mengakses objek bersarang Javascript dengan aman atau Mengakses objek JavaScript bersarang dengan kunci string . Tapi bagaimanapun: "Sayangnya, Anda tidak dapat mengakses array bersarang dengan trik ini." Kenapa tidak? Array adalah objek, jadi ia seharusnya bekerja dengan baik. Bisakah Anda memberikan contoh di mana tidak?
Felix Kling
1
@FelixKling Ketika kami mencoba mengakses array dengan pola Oliver Steele, kami tidak akan dapat membuat array pada panjang 'n' dengan cepat dan mengakses indeks ke-n tanpa mendapatkan kesalahan 'tidak terdefinisi'. Ex. ((user || {}).address || new Array(3))[1].name
Dinesh Pandiyan
3
Anda tidak menerapkan pola Anda secara konsisten. Tentu saja ...[1].barakan menghasilkan kesalahan jika elemen 1tidak ada. Tapi itu juga terjadi ....foo.barjika footidak ada. Anda harus "menjaga" akses 1juga, sama seperti Anda "menjaga" akses properti lainnya. Array hanyalah sebuah objek. "Elemen array" hanyalah sebuah properti. Diterapkan dengan benar akan (((user || {}).address || {})[1] || {}).name.
Felix Kling
1
Ini bagus. Itu tidak mengejutkan saya seperti ini. Terima kasih @FelixKling, saya akan memperbarui posting blog.
Dinesh Pandiyan
2
@DineshPandiyan Anda harus mengungkapkan bahwa Anda adalah penulis typy, saya baru saja datang ke sini setelah membaca posting blog Anda
reggaeguitar
8

Saya lebih suka JQuery. Lebih bersih dan mudah dibaca.

$.each($.parseJSON(data), function (key, value) {
  alert(value.<propertyname>);
});
Rudy Hinojosa
sumber
7

Mengakses objek multi level secara dinamis.

var obj = {
  name: "john doe",
  subobj: {
    subsubobj: {
      names: "I am sub sub obj"
    }
  }
};

var level = "subobj.subsubobj.names";
level = level.split(".");

var currentObjState = obj;

for (var i = 0; i < level.length; i++) {
  currentObjState = currentObjState[level[i]];
}

console.log(currentObjState);

Biola yang berfungsi: https://jsfiddle.net/andreitodorut/3mws3kjL/

Andrei Todorut
sumber
6

Jika Anda mencari satu atau lebih objek yang memenuhi kriteria tertentu, Anda memiliki beberapa opsi menggunakan query-js

//will return all elements with an id larger than 1
data.items.where(function(e){return e.id > 1;});
//will return the first element with an id larger than 1
data.items.first(function(e){return e.id > 1;});
//will return the first element with an id larger than 1 
//or the second argument if non are found
data.items.first(function(e){return e.id > 1;},{id:-1,name:""});

Ada juga singledan singleOrDefaultmereka bekerja sangat suka firstdan firstOrDefaultmasing - masing. Satu-satunya perbedaan adalah bahwa mereka akan melempar jika lebih dari satu pertandingan ditemukan.

untuk penjelasan lebih lanjut tentang query-js Anda bisa mulai dengan posting ini

Rune FS
sumber
Saya ingin tahu bagaimana ini bisa diperbaiki. Mau meninggalkan komentar?
Rune FS
6

The Underscore js Way

Yang merupakan pustaka JavaScript yang menyediakan seluruh functional programmingbantuan yang bermanfaat tanpa perlu memperluas objek bawaan.

Larutan:

var data = {
  code: 42,
  items: [{
    id: 1,
    name: 'foo'
  }, {
    id: 2,
    name: 'bar'
  }]
};

var item = _.findWhere(data.items, {
  id: 2
});
if (!_.isUndefined(item)) {
  console.log('NAME =>', item.name);
}

//using find - 

var item = _.find(data.items, function(item) {
  return item.id === 2;
});

if (!_.isUndefined(item)) {
  console.log('NAME =>', item.name);
}
Mohan Dere
sumber
6

Pertanyaan lama tetapi karena tidak ada yang menyebutkan lodash (hanya garis bawah).

Jika Anda sudah menggunakan lodash di proyek Anda, saya pikir cara yang elegan untuk melakukan ini dalam contoh kompleks:

Memilih 1

_.get(response, ['output', 'fund', 'data', '0', 'children', '0', 'group', 'myValue'], '')

sama dengan:

Memilih 2

response.output.fund.data[0].children[0].group.myValue

Perbedaan antara opsi pertama dan kedua adalah bahwa di Opt 1 jika Anda memiliki salah satu properti yang hilang (tidak terdefinisi) di jalan Anda tidak mendapatkan kesalahan, itu mengembalikan Anda parameter ketiga.

Untuk filter array lodash memiliki _.find()tetapi saya lebih suka menggunakan biasa filter(). Tapi saya masih berpikir metode di atas _.get()sangat berguna ketika bekerja dengan data yang sangat kompleks. Saya menghadapi API yang benar-benar kompleks di masa lalu dan itu berguna!

Saya harap ini dapat bermanfaat bagi siapa yang mencari opsi untuk memanipulasi data yang sangat rumit yang tersirat pada judulnya.

Thiago C. S Ventura
sumber
5

Saya tidak berpikir penanya hanya menyangkut objek bertingkat satu level, jadi saya menyajikan demo berikut untuk menunjukkan cara mengakses node objek json yang sangat bersarang. Baiklah, mari cari node dengan id '5'.

var data = {
  code: 42,
  items: [{
    id: 1,
    name: 'aaa',
    items: [{
        id: 3,
        name: 'ccc'
      }, {
        id: 4,
        name: 'ddd'
      }]
    }, {
    id: 2,
    name: 'bbb',
    items: [{
        id: 5,
        name: 'eee'
      }, {
        id: 6,
        name: 'fff'
      }]
    }]
};

var jsonloop = new JSONLoop(data, 'id', 'items');

jsonloop.findNodeById(data, 5, function(err, node) {
  if (err) {
    document.write(err);
  } else {
    document.write(JSON.stringify(node, null, 2));
  }
});
<script src="https://rawgit.com/dabeng/JSON-Loop/master/JSONLoop.js"></script>

dabeng
sumber
Bagaimana cara mengakses objek json bersarang menggunakan variabel. data = {a: {b: 'ss'}}; var key = ab data [key] tidak berfungsi
Pasupathi Rajamanickam
3

Anda dapat menggunakan sintaks jsonObject.keyuntuk mengakses nilai. Dan jika Anda ingin mengakses nilai dari array, maka Anda bisa menggunakan sintaks jsonObjectArray[index].key.

Berikut adalah contoh kode untuk mengakses berbagai nilai untuk memberi Anda ide.

        var data = {
            code: 42,
            items: [{
                id: 1,
                name: 'foo'
            }, {
                id: 2,
                name: 'bar'
            }]
        };

        // if you want 'bar'
        console.log(data.items[1].name);

        // if you want array of item names
        console.log(data.items.map(x => x.name));

        // get the id of the item where name = 'bar'
        console.log(data.items.filter(x => (x.name == "bar") ? x.id : null)[0].id);

Rahul Vala
sumber
3

Pendekatan dinamis

Dalam deep(data,key)fungsi di bawah ini , Anda dapat menggunakan keystring arbitrer - dalam kasus items[1].nameAnda (Anda dapat menggunakan notasi array [i]di level apa pun) - jika kunci tidak valid maka undefined adalah return.

Kamil Kiełczewski
sumber
2

Pendekatan pythonic, rekursif dan fungsional untuk mengurai pohon JSON sewenang-wenang:

handlers = {
    list:  iterate,
    dict:  delve,
    str:   emit_li,
    float: emit_li,
}

def emit_li(stuff, strong=False):
    emission = '<li><strong>%s</strong></li>' if strong else '<li>%s</li>'
    print(emission % stuff)

def iterate(a_list):
    print('<ul>')
    map(unravel, a_list)
    print('</ul>')

def delve(a_dict):
    print('<ul>')
    for key, value in a_dict.items():
        emit_li(key, strong=True)
        unravel(value)
    print('</ul>')

def unravel(structure):
    h = handlers[type(structure)]
    return h(structure)

unravel(data)

di mana data adalah daftar python (diurai dari string teks JSON):

data = [
    {'data': {'customKey1': 'customValue1',
           'customKey2': {'customSubKey1': {'customSubSubKey1': 'keyvalue'}}},
  'geometry': {'location': {'lat': 37.3860517, 'lng': -122.0838511},
               'viewport': {'northeast': {'lat': 37.4508789,
                                          'lng': -122.0446721},
                            'southwest': {'lat': 37.3567599,
                                          'lng': -122.1178619}}},
  'name': 'Mountain View',
  'scope': 'GOOGLE',
  'types': ['locality', 'political']}
]
pX0r
sumber
6
Pertanyaan ini tentang JavaScript, bukan Python. Tidak yakin apakah ada pertanyaan yang setara untuk Python.
Felix Kling
2

Fungsi grep jQuery memungkinkan Anda memfilter array:

var data = {
    code: 42,
    items: [{
        id: 1,
        name: 'foo'
    }, {
        id: 2,
        name: 'bar'
    }]
};

$.grep(data.items, function(item) {
    if (item.id === 2) {
        console.log(item.id); //console id of item
        console.log(item.name); //console name of item
        console.log(item); //console item object
        return item; //returns item object
    }

});
// Object {id: 2, name: "bar"}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>


sumber
2
// const path = 'info.value[0].item'
// const obj = { info: { value: [ { item: 'it works!' } ], randominfo: 3 }  }
// getValue(path, obj)

export const getValue = ( path , obj) => {
  const newPath = path.replace(/\]/g, "")
  const arrayPath = newPath.split(/[\[\.]+/) || newPath;

  const final = arrayPath.reduce( (obj, k) => obj ?  obj[k] : obj, obj)
  return final;
}
Michael Dimmitt
sumber
-4

Saya stringdataberasal dari file PHP tetapi masih, saya tunjukkan di sini di var. Ketika saya langsung mengambil json saya ke objdalamnya tidak akan menunjukkan itu sebabnya saya meletakkan file json saya sebagai

var obj=JSON.parse(stringdata); jadi setelah itu saya mendapatkan messageobj dan ditampilkan di kotak peringatan kemudian saya dapatkan datayang merupakan json array dan menyimpannya dalam satu variabel ArrObjkemudian saya membaca objek pertama dari array itu dengan nilai kunci seperti iniArrObj[0].id

     var stringdata={
        "success": true,
        "message": "working",
        "data": [{
                  "id": 1,
                  "name": "foo"
         }]
      };

                var obj=JSON.parse(stringdata);
                var key = "message";
                alert(obj[key]);
                var keyobj = "data";
                var ArrObj =obj[keyobj];

                alert(ArrObj[0].id);
Manthan Patel
sumber
2
Contohnya membingungkan karena stringjsonbukan string.
Felix Kling