Yuvalanmış nesnelere, dizilere veya JSON'a nasıl erişebilir ve işleyebilirim?


875

Nesneler ve diziler içeren bir iç içe veri yapısı var. Bilgileri nasıl çıkarabilirim, yani belirli veya birden çok değere (veya anahtarlara) erişebilirim?

Örneğin:

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

İçindeki nameikinci öğeye nasıl erişebilirim items?


22
@Marcel: "Veri iç içe veri yapım veya JSON var, belirli bir değere nasıl erişebilirim?" Şeklinde okunmalıdır . Ben farkı biliyor, ancak birçok insan yerine "nesne" den "JSON" araması olabilir değil ve yoktur. Birçok soru aslında "bu JSON'da X'e nasıl erişebilirim" şeklindedir. Cevabımda JSON'dan bahsettiğim tek yer, ne olduğunu açıkladığım yer. Bunu daha iyi bir şekilde nasıl ileteceğinize dair bir öneriniz varsa, tamamen kulaklarım.
Felix Kling

olası JSON bul
Travis J

Yanıtlar:


1159

Hazırlıklar

JavaScript'in birden fazla değer içerebilecek tek bir veri türü vardır: Nesne . Bir Dizi nesnenin özel bir şeklidir.

(Düz) Nesneler şu şekildedir:

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

Diziler şu şekildedir

[value, value, ...]

Hem diziler hem de nesneler bir key -> valueyapı ortaya çıkarır . Bir dizideki anahtarlar sayısal olmalıdır, oysa herhangi bir dize nesnelerde anahtar olarak kullanılabilir. Anahtar / değer çiftlerine "özellikler" de denir .

Özelliklere nokta gösterimi kullanılarak erişilebilir

const value = obj.someProperty;

veya braket notasyonu , özellik adı geçerli bir JavaScript olmazdı eğer tanımlayıcı adını [Spec] veya adı değişkenin değerdir:

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

Bu nedenle, dizi öğelerine yalnızca köşeli ayraç gösterimi kullanılarak erişilebilir:

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

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

Bekle ... JSON ne olacak?

JSON, XML, YAML, CSV ve diğerleri gibi verilerin metinsel bir temsilidir. Bu tür verilerle çalışmak için öncelikle JavaScript veri türlerine, yani dizilere ve nesnelere (ve bunlarla nasıl çalışılacağı açıklanmıştır) dönüştürülmelidir. JavaScript'te ayrıştırma JSON sorusunda JSON nasıl ayrıştırılır ? .

İlave okuma materyalleri

Dizilere ve nesnelere nasıl erişileceği temel JavaScript bilgisidir ve bu nedenle MDN JavaScript Kılavuzunu , özellikle bölümleri okumanız önerilir.



İç içe veri yapılarına erişme

Yuvalanmış veri yapısı, diğer dizilere veya nesnelere başvuran bir dizi veya nesnedir, yani değerleri diziler veya nesnelerdir. Bu tür yapılara art arda nokta veya köşeli parantez notasyonu uygulanarak erişilebilir.

İşte bir örnek:

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

nameİkinci öğeye erişmek istediğimizi varsayalım .

Bunu adım adım nasıl yapabiliriz:

Gördüğümüz gibi databir nesne, dolayısıyla nokta gösterimini kullanarak özelliklerine erişebiliyoruz. itemsAşağıdaki gibi özellik erişilen:

data.items

Değer bir dizidir, ikinci öğesine erişmek için parantez notasyonu kullanmamız gerekir:

data.items[1]

Bu değer bir nesnedir ve nameözelliğe erişmek için nokta gösterimini tekrar kullanırız . Sonuçta:

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

Alternatif olarak, özellikle ad nokta gösterimi kullanımı için geçersiz kılacak karakterler içeriyorsa, özelliklerin herhangi biri için köşeli ayraç gösterimini kullanabilirdik:

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

Bir mülke erişmeye çalışıyorum ama sadece undefinedgeri dönüyorum?

Çoğu zaman undefined, nesne / dizi bu ada sahip bir özelliğe sahip değildir.

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

Nesnenin / dizinin yapısını kullanın console.logveya console.dirdenetleyin. Erişmeye çalıştığınız özellik aslında iç içe geçmiş bir nesnede / dizide tanımlanmış olabilir.

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

Özellik adları dinamikse ve bunları önceden bilmiyorsam ne olur?

Özelliği adlarının bilinmediği ya da bir nesnenin bütün özelliklerine ulaşmak için / bir dizi elemanları, kullanabiliriz for...in [MDN] nesneler için döngü ve for [MDN] tüm özellikleri / elemanları üzerinde ilerlerken diziler için döngü.

Nesneler

Öğesinin tüm özelliklerini datayinelemek için, nesne üzerinde şöyle yineleme yapabiliriz :

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
}

Nesnenin nereden geldiğine (ve ne yapmak istediğinize) bağlı olarak, her yinelemede özelliğin gerçekten nesnenin bir özelliği mi yoksa miras alınan bir özellik mi olduğunu test etmeniz gerekebilir. Bunu Object#hasOwnProperty [MDN] ile yapabilirsiniz .

İçin alternatif olarak for...inbirlikte hasOwnPropertykullanabileceğiniz Object.keys [MDN] bir olsun özellik adları dizisi :

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

Diziler

data.items Dizinin tüm öğelerini yinelemek için bir fordöngü kullanırız :

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`.
}

for...inDiziler üzerinde yineleme yapmak için de kullanılabilir , ancak bundan kaçınılması gereken nedenler vardır: Neden 'for (listedeki öğe)' dizisi JavaScript'te kötü uygulama olarak kabul edilir? .

ECMAScript 5'in artan tarayıcı desteği ile dizi yöntemi forEach [MDN] de ilginç bir alternatif haline geliyor:

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

ES2015'i (ES6) destekleyen ortamlarda , yalnızca diziler için değil , aynı zamanda yinelenebilirler için de çalışan [MDN] döngüsünü kullanabilirsiniz :for...of

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

Her yinelemede, for...ofdoğrudan bize yinelemenin bir sonraki öğesini verir, erişmek veya kullanmak için bir "dizin" yoktur.


Veri yapısının "derinliği" benim için bilinmiyorsa ne olur?

Bilinmeyen anahtarlara ek olarak, veri yapısının "derinliği" (yani kaç tane iç içe nesne) sahip olduğu da bilinmiyor olabilir. Derin yuvalanmış özelliklere nasıl erişilir genellikle veri yapısına bağlıdır.

Ancak veri yapısı, örneğin ikili bir ağacın temsili gibi yinelenen desenler içeriyorsa, çözüm tipik olarak veri yapısının her bir seviyesine tekrar tekrar [Wikipedia] erişimini içerir.

İşte bir ikili ağacın ilk yaprak düğümünü almak için bir örnek:

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

Bilinmeyen tuşları ve derinliği olan bir iç içe veri yapısına erişmenin daha genel bir yolu, değerin türünü sınamak ve buna göre hareket etmektir.

İç içe veri yapısı içindeki tüm ilkel değerleri bir diziye ekleyen bir örnek (herhangi bir işlev içermediği varsayılarak). Bir nesneyle (veya diziyle) karşılaşırsak toArray, o değere tekrar çağırırız (özyinelemeli çağrı).

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



Yardımcılar

Karmaşık bir nesnenin veya dizinin yapısı mutlaka belli olmadığından, nasıl ilerleyeceğine karar vermek için her adımdaki değeri inceleyebiliriz. console.log [MDN] ve console.dir [MDN] bunu yapmamıza yardımcı oluyor. Örneğin (Chrome konsolunun çıktısı):

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

Burada data.itemsbunun her iki nesne olan iki öğeden oluşan bir dizi olduğunu görüyoruz . Chrome konsolunda nesneler hemen genişletilebilir ve denetlenebilir.

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

Bu bize bunun data.items[1]bir nesne olduğunu söyler ve onu genişlettikten sonra üç özelliği olduğunu görürüz id, nameve __proto__. İkincisi, nesnenin prototip zinciri için kullanılan dahili bir özelliktir. Yine de, prototip zinciri ve miras bu cevabın kapsamı dışındadır.


3
Burada bağlantılı olanlardan bazıları gerçekten bunu jQuery'de nasıl yapacağınızı soruyor, bu adil olmak 1 veya 2 şeyi basitleştiriyor. Bunu bir megaposttan daha fazla yapmak veya ayrı ayrı cevaplamaktan emin değilim - burada bir nesnenin ne olduğu hakkında temel bilgiler, bir dizi nedir genellikle sorulan şeydir ....
Chris Moschini

1
@ felix-kling Bir şey ... gibi iç içe nesnelerle, bu let object = {a: 1, b: 2, c: { a: 3, b: 4 }};her iç içe nesne için bir dizi içeren bir dizi döndürür, bu durumda [ 1, 2, [ 3, 4 ] ]itme yerine özyinelemeli çağrıda concat kullanmak daha iyi olmaz mıydı? (sonucun değişebilir olmasını gerektirir)
ElFitz

3
Bu, Stack Overflow'da gördüğüm en derinlemesine cevap - ve sorumu yanıtladı! Teşekkürler!
William Jones

bu bir sayfa ARRAY ve OBJ arasındaki farkı öğrenmemi
sağladı

76

Bu şekilde erişebilirsiniz

data.items[1].name

veya

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

Her iki yol da eşittir.


Evet ama veri ["öğeler"] yapamazsınız. 1.name
neaumusic

5
İlk çok daha sezgisel, okunabilir ve daha kısa;) Parantez özelliği sözdizimini yalnızca özellik adı değişken olduğunda kullanmayı tercih ederim.
DanteTheSmith

35

itemÖrnek yapıdan bir idveya tarafından namedizideki konumunu bilmeden erişmeye çalışıyorsanız , bunu yapmanın en kolay yolu underscore.js kütüphane:

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

Deneyimlerime göre, forya da for..indöngüler yerine daha yüksek dereceli işlevler kullanmak, akıl yürütmesi daha kolay ve dolayısıyla daha sürdürülebilir kodla sonuçlanır.

Sadece 2 sentim.


29

Nesneler ve diziler, verilerin işlenmesinde size yardımcı olabilecek birçok yerleşik yöntem içerir.

Not: Örneklerin çoğunda ok işlevlerini kullanıyorum . İşlev ifadelerine benzerler , ancak thisdeğeri sözcüksel olarak bağlarlar .

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

Object.keys()nesne anahtarları Object.values()dizisini döndürür, nesne değerleri Object.entries()dizisini döndürür ve nesne anahtarları dizisini ve karşılık gelen değerleri bir biçimde döndürür [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() for-loop ve yıkıcı atama ile

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

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

Object.entries()Bir for-loop ve yıkım ataması sonucunu yinelemek çok uygun .

For-of loop, dizi öğelerini tekrarlamanızı sağlar. Sözdizimi for (const element of array)( veya constile değiştirebiliriz , ancak değiştirmek istemiyorsak kullanmak daha iyidir ).varletconstelement

Yıkım ataması, bir diziden veya nesneden değerleri çıkarmanıza ve bunları değişkenlere atamanıza olanak tanır. Bu durumda diziyi const [key, value]atamak yerine, [key, value]dizinin elementilk öğesini keyve ikinci öğesini atamak anlamına gelir value. Buna eşdeğerdir:

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

Gördüğünüz gibi yıkım, bunu çok daha basit hale getiriyor.

Array.prototype.every() ve Array.prototype.some()

Dizinin her öğesi için belirtilen geri çağrı işlevi döndürülürse every()yöntem döndürülür . Yöntem döner ise belirtilen geri arama işlevi döner için bazı (en azından bir) elemanı.truetruesome()truetrue

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() ve Array.prototype.filter()

find()Yöntem döndüren birinci hangi tatmin sağlanan geri arama işlevi elemanı. filter()Yöntem bir dizi döndürür her hangi tatmin sağlanan geri arama işlevi elemanları.

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

map()Yöntem dizi elemanları üzerinde bir mesafede geri arama işlevini çağırmak sonuçları ile bir dizi döndürür.

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

reduce()Yöntem iki elemanları ile donatılmış bir geri arama fonksiyonunu çağırarak tek bir değer için bir dizi azaltır.

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

reduce()Yöntem olup, başlangıç değeri isteğe bağlı ikinci bir parametre alır. Bu, üzerinde arama yaptığınız dizi reduce()sıfır veya bir öğeye sahip olduğunda faydalıdır . Örneğin, sum()bir diziyi bağımsız değişken olarak alan ve tüm öğelerin toplamını döndüren bir işlev oluşturmak istersek, şöyle yazabiliriz:

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


Bu benim en sevdiğim cevap. Ayrıca, döngü için sadece iç içe geçmiş veriler gibi bir örnek de ekleyebilirsinizObject.keys(data["items"]).forEach(function(key) { console.log(data["items"][key].id); console.log(data["items"][key].name); });
SilverSurfer

25

Bazen, bir dize kullanarak iç içe geçmiş bir nesneye erişmek arzu edilebilir. Basit yaklaşım ilk seviyedir, örneğin

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

Ancak bu, karmaşık jsonlarda genellikle böyle değildir. Json daha karmaşık hale geldikçe, json'un içinde değer bulma yaklaşımları da karmaşık hale gelir. Json'da gezinmek için özyinelemeli bir yaklaşım en iyisidir ve bu özyinelemenin nasıl kullanıldığına bakılması, aranan verilerin türüne bağlı olacaktır. Koşullu ifadeler varsa, json arama kullanmak için iyi bir araç olabilir.

Erişilen özellik zaten biliniyorsa, ancak yol karmaşıksa, örneğin bu nesnede

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

Nesnede dizinin ilk sonucunu almak istediğinizi biliyorsunuzdur, belki de kullanmak istersiniz

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

Ancak, bu ada sahip bir nesnenin özelliği olmadığından bu bir istisnaya neden olur. Bunu kullanabilmenin çözümü, nesnenin ağaç yönünü düzleştirmek olacaktır. Bu özyinelemeli olarak yapılabilir.

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

Şimdi, karmaşık nesne düzleştirilebilir

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

İşte jsFiddle Demobu yaklaşımlardan biri.


obj["arr[0].name"]Bunun yerine WTH kullanmak ister misiniz obj.arr[0].name? Serileştirme dışında düzleştirilmiş nesnelerle uğraşmak zorunda değilsiniz .
Bergi

@Bergi - Bu soruyu yaygın olarak görüyorum ve bu kurallı olarak kullanıldığından, bu sürümüne bir cevap gönderdim. Önlenebilirse obj.arr [0] .name kullanmak çok daha hızlıdır, ancak bazen insanlar dize erişimcilerini etrafından geçirmek isterler ve bu da buna bir örnektir.
Travis J

Urgh. Yine de, tüm nesneyi yalnızca tek bir dize yolu kullanmak için düzleştirmek için pek bir neden yoktur, bunu ayrıştırıp dinamik bir arama yapabilirsiniz.
Bergi

14

Bu soru oldukça eski, çağdaş bir güncelleme gibi. ES2015'in başlamasıyla, ihtiyacınız olan verileri elde etmenin alternatifleri vardır. Artık iç içe geçmiş nesnelere erişmek için nesne yok etme adı verilen bir özellik var .

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

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

console.log(secondName);

Yukarıdaki örnek olarak adlandırılan bir değişken oluşturur secondNamegelen nameadı verilen bir dizi anahtar items, yalnız ,dizideki ilk nesne atlama söylüyor.

Basit bir dizi erişiminin okunması daha kolay olduğundan, genel olarak nesneleri parçalarken faydalı olur.

Bu sizin özel kullanım durumunuza çok kısa bir giriş, yıkım ilk başta alışılmadık bir sözdizimi olabilir. Daha fazla bilgi için Mozilla'nın Yıkıcı Atama belgelerini okumanızı tavsiye ederim .


13

Yuvalanmış bir özniteliğe erişmek için adını belirtmeniz ve ardından nesne içinde arama yapmanız gerekir.

Kesin yolu zaten biliyorsanız, komut dosyanızda şu şekilde sabit kodlayabilirsiniz:

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

bunlar da işe yarıyor -

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

Elden önce tam adı bilmediğinizde veya sizin için adı sağlayan kullanıcıdır. Daha sonra veri yapısı üzerinden dinamik olarak arama yapmak gerekir. Bazıları burada bir fordöngü kullanarak aramanın yapılabileceğini öne sürdü , ancak kullanarak bir yoldan geçmek için çok basit bir yol var 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)

Yol şunu söylemenin bir yoludur: İlk olarak nesneyi bir anahtar itemsolan anahtarla alın . Sonra 1-st öğesini alın (0 dizin dizisi). Son olarak nesneyi name, dizi öğesinde anahtar olan anahtarla birlikte alın bar.

Çok uzun bir yolunuz varsa, String.splittüm bunları kolaylaştırmak için bile kullanabilirsiniz -

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

Bu, jQuery veya lodash gibi üçüncü taraf kitaplıkları kullanmadan sadece düz bir JavaScripttir.


13
var ourStorage = {


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

veya

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

Temel olarak, altında açılan her torun arasında bir nokta kullanın ve iki dizeden yapılmış nesne adlarınız varsa, ["obj Name"] gösterimini kullanmalısınız. Aksi takdirde, sadece bir nokta yeterlidir;

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

buna eklemek için iç içe dizilere erişmek şöyle olur:

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"

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

Yukarıdaki durumu gösteren başka bir faydalı belge: https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Basics#Bracket_notation

Nokta yürüme yoluyla mülk erişimi: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Property_Accessors#Dot_notation


Bu bağlantı soruyu cevaplayabilse de, cevabın temel kısımlarını buraya eklemek ve bağlantıyı referans olarak sağlamak daha iyidir. Bağlantı verilen sayfa değişirse, yalnızca bağlantı yanıtları geçersiz olabilir. - Yorumdan
Robert

1
Gönderiyi düzenledim. Her ne kadar insanlar ona kötü temsilcisi vermek için hızlı. Bir dahaki sefere cevap vermekten kaçınacağım.
Johnny

1
@Riddick kaçınmayın, sadece bir bağlantı göndermediğinizden emin olun
reggaeguitar

12

lodash _getFonksiyonu kullanabilirsiniz :

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

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

9

Bir kütüphane eklemek istiyorsanız JSONPath kullanmak en esnek çözümlerden biri olacaktır: https://github.com/s3u/JSONPath (düğüm ve tarayıcı)

Kullanım durumunuz için json yolu:

$..items[1].name

yani:

var secondName = jsonPath.eval(data, "$..items[1].name");

1
Eval () kullanmak iyi bir çözüm değildir. Bunun yerine birinci sınıf fonksiyon kullanılabilir.
pradeep gowda

8

Her ihtimale karşı, herkes en sonra 2017 veya bu soruyu ziyaret edip bir arayan kolay hatırlamak yolu, burada ayrıntılı bir blog yazısı var Erişim İç içe JavaScript nesneleri tarafından hortumlama olmadan

Undefined 'foo' özelliği okunamıyor hatasının

1. Oliver Steele'nin iç içe nesne erişim düzeni

En kolay ve en temiz yol Oliver Steele'nin iç içe nesne erişim modelini kullanmaktır

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

Bu notasyon ile asla karşılaşmayacaksın

Undefined öğesinin 'name' özelliği okunamıyor .

Temel olarak kullanıcının var olup olmadığını kontrol edersiniz, eğer yoksa anında boş bir nesne yaratırsınız. Bu şekilde, bir sonraki seviye anahtara her zaman var olan bir nesneden veya boş bir nesneden erişilir , ancak asla tanımsızdan erişilir .

2. Dizi Azaltma Kullanarak İç İçe Nesnelere Erişin

İç içe dizilere erişebilmek için kendi dizi azaltma util'inizi yazabilirsiniz.

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.

Ayrıca sizin için tüm bunları yapan mükemmel bir tür işleme minimal kütüphane türü vardır.


3
Bu soru öncelikle var olan erişim özellikleriyle ilgilidir. Neye atıfta bulunduğunuzla ilgili bir soru zaten var (ve zaten çözümlerinizin çoğunu dahil ediyor): Javascript iç içe geçmiş nesnelere güvenli bir şekilde erişin veya İç içe JavaScript nesnelerine dize anahtarıyla erişme . Ama yine de: "Ne yazık ki, bu hile ile iç içe dizilere erişemezsiniz." Neden olmasın? Diziler nesnedir, bu yüzden de iyi çalışmalıdır. Bunun olmadığı bir örnek verebilir misiniz?
Felix Kling

1
@FelixKling Oliver Steele deseniyle dizilere erişmeye çalıştığımızda, 'tanımsız' hata almadan anında 'n' uzunluğunda dizi oluşturamaz ve n. Dizinine erişemeyiz. Ör. ((user || {}).address || new Array(3))[1].name
Dinesh Pandiyan

3
Deseninizi tutarlı bir şekilde uygulamıyorsunuz. Tabii ki ...[1].bareleman olmasaydı bir hatayla sonuçlanırdı 1. Ama ....foo.bareğer olmasaydı da böyledir foo. 1Diğer mülk erişimini "koruduğunuz" gibi, erişimi de "korumanız" gerekir. Dizi sadece bir nesnedir. "Dizi elemanı" sadece bir özelliktir. Doğru uygulanmış olur (((user || {}).address || {})[1] || {}).name.
Felix Kling

1
Bu harika. Bana bu şekilde vurmadı. Teşekkürler @FelixKling, blog yazılarını güncelleyeceğim.
Dinesh Pandiyan

2
@DineshPandiyan Eğer typy yazar olduğunu açıklamak gerekir, ben sadece blog yazınızı okuduktan sonra geldi
reggaeguitar

8

JQuery'yi tercih ederim. Daha temiz ve okunması kolay.

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

7

Dinamik olarak çok düzeyli nesneye erişme.

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

Çalışan keman: https://jsfiddle.net/andreitodorut/3mws3kjL/


6

Belirli ölçütleri karşılayan bir veya daha fazla nesne arıyorsanız query-js kullanarak birkaç seçeneğiniz vardır

//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:""});

Orada da bir var singleve bir singleOrDefaultde çok gibi çalışır firstve firstOrDefaultsırasıyla. Tek fark, birden fazla eşleşme bulunursa fırlatacaklarıdır .

Sorgu-js daha sonraki açıklamaları için bu başlayabilirsiniz yazı


Bunun nasıl geliştirilebileceğini bilmek isterim. Yorum bırakmak ister misin?
Rune FS

6

Alt çizgi js yolu

Hangi yararlı bir karmaşa sağlayan bir JavaScript kitaplığı functional programming yerleşik nesneleri genişletmeden yardımcıları .

Çözüm:

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

6

Eski bir soru ama kimsenin bahsetmediği gibi (sadece alt çizgi).

Projenizde zaten lodash kullanıyorsanız, bunu karmaşık bir örnekte yapmanın zarif bir yolu olduğunu düşünüyorum:

Seçenek 1

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

ile aynı:

Seçenek 2

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

Birinci ve ikinci seçenek arasındaki fark Opt 1 yolda eksik (tanımsız) özelliklerden birine sahipseniz bir hata almazsanız, üçüncü parametreyi döndürmesidir.

Dizi filtre lodash var _.find()ama ben normal kullanmak istiyorum filter(). Ama yine de yukarıdaki yöntemin _.get()gerçekten karmaşık verilerle çalışırken süper yararlı olduğunu düşünüyorum . Geçmişte gerçekten karmaşık API'lerle karşılaştım ve kullanışlı oldu!

Umarım, başlığın ima ettiği gerçekten karmaşık verileri manipüle etmek için seçenekleri arayanlar için yararlı olabilir.


5

Ben sadece sadece bir düzey iç içe nesne endişe sorgulayıcı sanmıyorum, bu yüzden derinden iç içe json nesnesinin düğüm erişmek nasıl göstermek için aşağıdaki demo sunuyoruz. Pekala, '5' kimliğine sahip düğümü bulalım.

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>


Değişkenleri kullanarak iç içe json nesnesine nasıl erişirim? veri = {a: {b: 'ss'}}; var anahtar = ab veri [anahtar] çalışmıyor
Pasupathi Rajamanickam

3

Değere jsonObject.keyerişmek için sözdizimini kullanabilirsiniz . Ve bir diziden bir değere erişmek istiyorsanız, sözdizimini kullanabilirsiniz jsonObjectArray[index].key.

İşte size fikir vermek için çeşitli değerlere erişmek için kod örnekleri.

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


3

Dinamik yaklaşım

Aşağıdaki deep(data,key)işlevde, rasgele keydize kullanabilirsiniz - sizin durumunuzda items[1].name( [i]herhangi bir düzeyde dizi gösterimini kullanabilirsiniz ) - anahtar geçersizse tanımsız döndürülür.


2

Keyfi JSON ağaçlarını çözmek için pitonik, özyinelemeli ve işlevsel bir yaklaşım:

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)

burada veriler bir python listesidir (bir JSON metin dizesinden ayrıştırılır):

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

6
Bu soru Python ile değil JavaScript ile ilgilidir. Python için eşdeğer bir soru olup olmadığından emin değilim.
Felix Kling

2

jQuery'nin grep işlevi bir dizi boyunca filtreleme yapmanıza olanak tanır:

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>


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


-4

Benim stringdataPHP dosyasından geliyor ama yine de burada belirtiyorum var. Doğrudan içine benim json almak zaman objhiçbir şey göstermek gibi neden benim json dosyası koymak

var obj=JSON.parse(stringdata); bundan sonra ben messageobj almak ve uyarı kutusunda göstermek sonra datajson dizi ve bir değişken içinde depolamak ArrObjsonra bu gibi anahtar değeri ile bu dizinin ilk nesnesi okumakArrObj[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);

2
Örnek kafa karıştırıcıdır çünkü stringjsonbir dize değildir.
Felix Kling

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.