중첩 된 객체, 배열 또는 JSON에 액세스하고 처리하려면 어떻게해야합니까?


875

객체와 배열을 포함하는 중첩 된 데이터 구조가 있습니다. 정보를 추출하는 방법, 즉 특정 또는 여러 값 (또는 키)에 액세스하는 방법은 무엇입니까?

예를 들면 다음과 같습니다.

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

name의 두 번째 항목에 items어떻게 액세스 할 수 있습니까?


22
@Marcel : "데이터 중첩 데이터 구조 나 JSON이 있는데 어떻게 특정 값에 액세스 할 수 있습니까?" 로 읽어야 합니다. 나는 그 차이를 알고 있지만 많은 사람들이 오히려 "개체"가 아닌 "JSON"에 대한 검색 될 수 없으며 않습니다. 실제로 많은 질문은 "이 JSON에서 X에 액세스하는 방법"형식입니다. 내 대답에서 JSON을 언급하는 유일한 곳은 그것이 무엇인지 설명하는 곳입니다. 더 나은 방법으로 이것을 전달하는 방법에 대한 제안이 있다면, 나는 모두 귀입니다.
— Felix Kling

답변:


1159

예비

JavaScript에는 여러 값을 포함 할 수있는 하나의 데이터 유형 ( Object) 만 있습니다. 배열 객체의 특별한 형태이다.

(일반) 물체의 형태는

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

배열의 형태는

[value, value, ...]

배열과 객체 모두 key -> value구조를 노출합니다 . 배열의 키는 숫자 여야하지만 모든 문자열은 객체의 키로 사용할 수 있습니다. 키-값 쌍은 "properties" 라고도합니다 .

점 표기법을 사용하여 속성에 액세스 할 수 있습니다

const value = obj.someProperty;

또는 괄호 표기 , 속성 이름이 유효한 JavaScript 않을 것인지 식별자 이름 [사양] 또는 이름 변수 값이다 :

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

이런 이유로 배열 요소는 대괄호 표기법을 통해서만 액세스 할 수 있습니다.

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

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

잠깐만 ... JSON은 어떻습니까?

JSON은 XML, YAML, CSV 등과 같은 텍스트의 텍스트 표현입니다. 이러한 데이터로 작업하려면 먼저 배열 및 객체와 같은 JavaScript 데이터 유형으로 변환해야합니다 (그리고 이러한 작업을 수행하는 방법은 방금 설명했습니다). JSON을 구문 분석하는 방법 은 JavaScript에서 JSON 구문 분석 질문에 설명되어 있습니다 . .

추가 자료

배열과 객체에 액세스하는 방법은 기본적인 JavaScript 지식이므로 MDN JavaScript 안내서 , 특히 섹션 을 읽는 것이 좋습니다.



중첩 된 데이터 구조에 액세스

중첩 된 데이터 구조는 다른 배열 또는 객체를 참조하는 배열 또는 객체입니다. 즉, 값은 배열 또는 객체입니다. 도트 또는 브래킷 표기법을 연속적으로 적용하여 이러한 구조에 액세스 할 수 있습니다.

예를 들면 다음과 같습니다.

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

name두 번째 항목 에 액세스하려고한다고 가정 해 봅시다 .

다음은 단계별로 수행 할 수있는 방법입니다.

우리가 볼 수 있듯이 data객체는 점 표기법을 사용하여 속성에 액세스 할 수 있습니다. items속성은 다음과 같습니다 액세스 할 수 있습니다 :

data.items

값은 배열이며, 두 번째 요소에 액세스하려면 대괄호 표기법을 사용해야합니다.

data.items[1]

이 값은 객체이며 점 표기법을 다시 사용하여 name속성 에 액세스합니다 . 결국 우리는 다음을 얻습니다.

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

또는 이름에 점 표기법 사용에 유효하지 않은 문자가 포함 된 경우 속성에 대괄호 표기법을 사용할 수 있습니다.

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

속성에 액세스하려고하는데 undefined다시 돌아 오나요?

대부분의 경우 undefined객체 / 어레이에는 해당 이름의 속성이 없습니다.

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

객체 / 배열의 구조를 사용 console.log하거나 console.dir검사하십시오. 액세스하려는 속성이 실제로 중첩 된 객체 / 배열에 정의되어있을 수 있습니다.

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

속성 이름이 동적이고 미리 알 수 없으면 어떻게합니까?

속성 이름을 알 수 없거나 배열의 객체 / 요소에 대한 모든 속성에 액세스하려는 경우 객체에 for...in [MDN] 루프를 사용하고 배열에 for [MDN] 루프를 사용하여 모든 속성 / 요소를 반복 할 수 있습니다.

사물

의 모든 속성을 반복하기 위해 다음과 같이 객체를data 반복 할 수 있습니다 .

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
}

객체의 위치와 수행하려는 작업에 따라 속성이 실제로 객체의 속성인지 아니면 상속 된 속성인지 각 반복에서 테스트해야 할 수도 있습니다. Object#hasOwnProperty [MDN]으로 이를 수행 할 수 있습니다 .

for...inwith 대신에 [MDN] 을 hasOwnProperty사용 하여 속성 이름 배열 을 얻을 수 있습니다 .Object.keys

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

배열

data.items 배열 의 모든 요소를 ​​반복 하기 위해 for루프를 사용합니다 .

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...in배열을 반복 하는 데 사용할 수도 있지만 이것을 피해야하는 이유가 있습니다. 배열에서 'for (var item in list)'가 JavaScript에서 나쁜 습관으로 간주되는 이유는 무엇입니까? .

ECMAScript 5의 브라우저 지원이 증가함에 따라 배열 방법 forEach [MDN]도 흥미로운 대안이되었습니다.

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 (ES6)를 지원하는 환경에서는 [MDN] 루프 를 사용할 수도 있습니다. [MDN] 루프는 배열뿐만 아니라 반복 가능한 작업 에도 사용할 수 있습니다 .for...of

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

각 반복 for...of에서 iterable의 다음 요소를 직접 제공하며 액세스하거나 사용할 "인덱스"가 없습니다.


데이터 구조의 "깊이"를 모르면 어떻게해야합니까?

알 수없는 키 외에도 데이터 구조의 "깊이"(예 : 중첩 된 개체 수)도 알 수 없습니다. 깊이 중첩 된 속성에 액세스하는 방법은 일반적으로 정확한 데이터 구조에 따라 다릅니다.

데이터 구조는 예를 들면 이진 트리의 표현의 반복 패턴을 포함하지만, 일반적으로 용액에 포함 재귀 [위키] 상기 데이터 구조의 각 레벨 액세스.

다음은 이진 트리의 첫 번째 리프 노드를 가져 오는 예입니다.

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

알 수없는 키와 깊이로 중첩 된 데이터 구조에 액세스하는보다 일반적인 방법은 값의 유형을 테스트하고 그에 따라 조치하는 것입니다.

다음은 중첩 된 데이터 구조 내의 모든 기본 값을 배열에 추가하는 예입니다 (함수를 포함하지 않는다고 가정). 객체 (또는 배열)가 발생하면 toArray해당 값을 다시 호출 합니다 (재귀 호출).

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



헬퍼

복잡한 객체 또는 배열의 구조가 반드시 명확하지는 않기 때문에 각 단계의 값을 검사하여 더 나아가는 방법을 결정할 수 있습니다. console.log [MDN] 및 console.dir [MDN] 이이 작업을 도와줍니다. 예를 들어 (Chrome 콘솔의 출력) :

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

여기서 우리 data.items는 이것이 두 객체 인 두 개의 요소를 가진 배열 임을 알 수 있습니다. Chrome 콘솔에서 개체를 즉시 확장하고 검사 할 수도 있습니다.

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

이는 우리에게 data.items[1]객체이며, 확장 후 우리가 세 가지 속성을 가지고 있음을 볼 수 id, name과 __proto__. 후자는 객체의 프로토 타입 체인에 사용되는 내부 속성입니다. 그러나 프로토 타입 체인과 상속은이 답변의 범위를 벗어납니다.


3
여기에 연결되는 일부는 실제로 jQuery 에서이 작업을 수행하는 방법을 묻는 것입니다. 공평하게 말하면 여기에서 1-2 가지를 단순화합니다. 이것을 메가 포스트로 만들지 또는 별도로 답할 것인지 확실하지 않습니다-배열이 무엇인지 객체에 대해 여기에서 다루는 기본 사항은 일반적으로 실제로 요청되는 것입니다 ....
— Chris Moschini

1
@ felix-kling 한 가지 ...와 같은 let object = {a: 1, b: 2, c: { a: 3, b: 4 }};중첩 된 객체의 경우 중첩 된 각 객체에 대한 배열을 포함하는 배열을 반환합니다.이 경우 [ 1, 2, [ 3, 4 ] ]푸시 대신 재귀 호출에서 concat을 사용하는 것이 더 좋지 않습니까? (결과를 변경할 수 있어야 함)
— ElFitz

3
이것은 스택 오버플로에서 본 것 중 가장 심층적 인 답변이며 내 질문에 대한 답변입니다! 감사!
— 윌리엄 존스

이 한 페이지에서 ARRAY와 OBJ의 차이점을 배울 수
— 있었습니다.

76

이 방법으로 액세스 할 수 있습니다

data.items[1].name

또는

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

두 가지 방법이 동일합니다.


네하지만 당신은 [ "항목"] 데이터를 할 수 없다 1.name.
— neaumusic

5
첫 번째는 훨씬 직관적이고 읽기 쉽고 짧습니다.) 속성 이름이 변수 일 때만 대괄호 속성 구문을 사용하는 것이 좋습니다.
— DanteTheSmith

35

배열의 위치를 ​​모르 거나 or 에 item의해 예제 구조에서 에 액세스하려는 경우 underscore.js 라이브러리 를 사용하는 것이 가장 쉬운 방법입니다 .idname

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

내 경험에 비추어 볼 때 for또는 for..in루프 대신 고차 함수를 사용 하면 추론하기 쉽고 코드를 유지 관리하기가 더 쉽습니다.

그냥 내 2 센트.


29

객체와 배열에는 데이터 처리에 도움이되는 내장 메서드가 많이 있습니다.

참고 : 많은 예제에서 화살표 함수를 사용하고 있습니다 . 그것들은 함수 표현식 과 비슷 하지만 this값을 어휘 적으로 바인딩합니다 .

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

Object.keys()객체의 키 Object.values()배열, 객체의 값 Object.entries()배열, 객체의 키 배열 및 해당 값을 형식으로 반환합니다 [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-of 루프와 파괴 할당

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

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

결과를 반복하는 것이 매우 편리합니다. Object.entries() 과를 에 대한-의 루프 와 destructuring 할당 .

For-of 루프를 사용하면 배열 요소를 반복 할 수 있습니다. 구문은 for (const element of array)(우리가 대체 할 수 const와 함께var 나 let,하지만 사용하는 것이 좋습니다 const우리가 수정하지 않으려는 경우element ).

할당 제거를 사용하면 배열 또는 객체에서 값을 추출하여 변수에 할당 할 수 있습니다. 이 경우 배열을 const [key, value]에 할당하는 대신 해당 [key, value]배열 element의 첫 번째 요소를key 번째 요소를 두 번째 요소를에value . 다음과 같습니다 :

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

보시다시피, 파괴는 이것을 훨씬 간단하게 만듭니다.

Array.prototype.every() 과 Array.prototype.some()

every()방법 리턴 true지정된 콜백 함수가 리턴하는 경우 true에 대한 모든 어레이 소자. some()메소드가 복귀 true하는 경우 지정된 콜백 함수의 복귀 true에 대한 일부 (적어도 하나)의 요소.

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

find()방법 리턴 제 만족시키는 제공된 콜백 함수 소자. 이 filter()메소드는 제공된 콜백 함수를 만족시키는 모든 요소 의 배열을 리턴합니다 .

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()메소드는 배열 요소에서 제공된 콜백 함수를 호출 한 결과와 함께 배열을 리턴합니다.

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()메소드는 두 개의 요소로 제공된 콜백 함수를 호출하여 배열을 단일 값으로 줄입니다.

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()방법은 선택적인 두 번째 매개 변수 (초기 값)를 사용합니다. 이것은 호출하는 배열에 reduce()0 개 또는 1 개의 요소가 있을 수있는 경우에 유용 합니다. 예를 들어, sum()배열을 인수로 사용하고 모든 요소의 합을 반환 하는 함수를 만들려면 다음과 같이 작성할 수 있습니다.

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


이것은 내가 가장 좋아하는 답변입니다. 또한 다음과 같이 Expecific 중첩 데이터 만 루프에 대한 예제를 추가 할 수 있습니다.Object.keys(data["items"]).forEach(function(key) { console.log(data["items"][key].id); console.log(data["items"][key].name); });
— SilverSurfer

25

때로는 문자열을 사용하여 중첩 객체에 액세스하는 것이 바람직 할 수 있습니다. 간단한 접근 방식이 첫 번째 수준입니다 (예 :

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

그러나 복잡한 json의 경우에는 종종 그렇지 않습니다. json이 더 복잡 해짐에 따라 json 내부의 값을 찾는 방법도 복잡해집니다. json을 탐색하는 재귀 적 접근 방식이 가장 좋으며 재귀를 활용하는 방법은 검색되는 데이터 유형에 따라 다릅니다. 조건문이 관련된 경우 json 검색 을 사용하는 것이 좋습니다.

액세스중인 속성이 이미 알려져 있지만이 개체와 같이 경로가 복잡한 경우

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

그리고 객체에서 배열의 첫 번째 결과를 얻고 싶다는 것을 알고 있습니다.

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

그러나 해당 이름을 가진 객체의 속성이 없으므로 예외가 발생합니다. 이것을 사용할 수있는 해결책은 객체의 트리 측면을 평평하게하는 것입니다. 이것은 재귀 적으로 수행 될 수 있습니다.

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

이제 복잡한 물체를 평평하게 할 수 있습니다

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

다음은 jsFiddle Demo이 접근법 중 하나 입니다.


obj["arr[0].name"]대신 WTH를 사용 obj.arr[0].name하시겠습니까? 직렬화를 제외하고 평평한 객체 를 처리 할 필요가 거의 없습니다 .
— Bergi

@ Bergi-나는이 질문을 일반적으로보고 있으며 이것이 정식으로 사용되고 있기 때문에 그 버전에 대한 답변을 게시했습니다. 피할 수 없다면 obj.arr [0] .name을 사용하는 것이 훨씬 빠르지 만 때로는 사람들이 문자열 접근자를 전달하고 싶을 때가 있습니다.
— 트래비스 J

어. 여전히 단일 문자열 경로를 사용하기 위해 전체 객체를 평평하게 만들 이유는 거의 없으므로 간단히 구문 분석하고 동적 조회를 수행 할 수 있습니다.
— Bergi

14

이 질문은 현대의 업데이트로 꽤 오래되었습니다. ES2015가 시작되면서 필요한 데이터를 확보 할 수있는 대안이 있습니다. 이제 중첩 객체에 액세스하기위한 객체 구조 해제라는 기능이 있습니다.

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

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

console.log(secondName);

위의 예제 는 외로운 이라는 배열 secondName의 name키에서 호출 된 변수를 만듭니다.items, 의 첫 번째 개체는 건너 뜁니다.

특히 간단한 배열 접근이 읽기 쉬우므로이 예제에서는 너무 과잉 일 수 있지만 일반적으로 객체를 분리 할 때 유용합니다.

이것은 특정 유스 케이스에 대한 간략한 소개이며, 처음에는 구조를 파괴하는 것이 특이한 구문 일 수 있습니다. 자세한 내용은 Mozilla의 Destructuring Assignment 문서 를 읽는 것이 좋습니다 .


13

중첩 된 속성에 액세스하려면 이름을 지정한 다음 객체를 검색해야합니다.

정확한 경로를 이미 알고 있다면 다음과 같이 스크립트로 하드 코딩 할 수 있습니다.

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

이것들도 작동합니다-

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

사전에 정확한 이름을 모르거나 사용자가 이름을 제공 한 사람인 경우. 그런 다음 데이터 구조를 통한 동적 검색이 필요합니다. 일부는 for루프를 사용하여 검색을 수행 할 수 있다고 제안 했지만을 사용하여 경로를 탐색하는 매우 간단한 방법이 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)

경로는 말할 수있는 방법입니다. 먼저 key로 객체를 가져 items오십시오. 그런 다음 1-st 요소 (0 개의 인덱스 배열)를 사용하십시오. 마지막 name으로 해당 배열 요소에 키가있는 객체를 가져옵니다 .이 문자열은 문자열입니다.bar . 입니다.

경로가 너무 길면 String.split이 모든 작업을보다 쉽게 ​​수행 할 수 있습니다.

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

이것은 jQuery 또는 lodash와 같은 타사 라이브러리를 사용하지 않고 일반 JavaScript입니다.


13
var ourStorage = {


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

또는

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

기본적으로 그 아래에 펼쳐지는 각 자손 사이에 점을 사용하고 두 문자열로 만들어진 오브젝트 이름이있는 경우 [ "obj Name"] 표기법을 사용해야합니다. 그렇지 않으면 점만으로 충분합니다.

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

이것에 추가하려면 중첩 배열에 액세스하면 다음과 같이됩니다.

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"

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

위 상황을 묘사 한 또 다른 유용한 문서 : https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Basics#Bracket_notation

도트 워킹을 통한 속성 액세스 : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Property_Accessors#Dot_notation


이 링크가 질문에 대한 답변을 제공 할 수 있지만 여기에 답변의 필수 부분을 포함시키고 참조 용 링크를 제공하는 것이 좋습니다. 링크 된 페이지가 변경되면 링크 전용 답변이 유효하지 않을 수 있습니다. - 리뷰에서
— Robert

1
게시물을 수정했습니다. 그럼에도 불구하고 사람들은 신속하게 나쁜 대답을했습니다. 다음에는 대답을 삼가겠습니다.
— Johnny

1
@Riddick은 자제하지 말고 링크 만 게시하지 않도록하십시오
— reggaeguitar

12

당신은 lodash _get기능을 사용할 수 있습니다 :

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

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

9

라이브러리를 포함 시키려는 경우 JSONPath를 사용 하는 것이 가장 유연한 솔루션 중 하나입니다. https://github.com/s3u/JSONPath (노드 및 브라우저)

사용 사례의 경우 json 경로는 다음과 같습니다.

$..items[1].name

그래서:

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

1
eval ()을 사용하는 것은 좋은 해결책이 아닙니다. 대신 일급 기능을 사용할 수 있습니다.
— pradeep gowda

8

2017 년 이후 에이 질문을 방문하고 기억하기 쉬운 방법 을 찾는 사람을 위해, JavaScript로 중첩 된 객체 에 액세스 하는 방법에 대한 정교한 블로그 게시물 이 있습니다.

정의되지 않은 'foo'속성을 읽을 수 없습니다 오류

1. Oliver Steele의 중첩 된 객체 액세스 패턴

가장 쉽고 깨끗한 방법은 Oliver Steele의 중첩 된 객체 액세스 패턴을 사용하는 것입니다

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

이 표기법으로, 당신은 절대로 실행되지 않습니다

정의되지 않은 'name'속성을 읽을 수 없습니다 .

기본적으로 사용자가 존재하는지 확인하고 그렇지 않은 경우 즉시 빈 개체를 만듭니다. 이런 식으로 다음 레벨 키는 존재하는 객체 또는 빈 객체에서 항상 액세스됩니다. 되지만 정의되지 않은 에서는 하지 않습니다.

2. Array Reduce를 사용하여 중첩 된 객체에 액세스

중첩 배열에 액세스하려면 자신 만의 array reduce util을 작성할 수 있습니다.

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.

이 모든 것을 수행 하는 최소한의 라이브러리 typy 를 처리하는 훌륭한 유형도 있습니다.


3
이 질문은 주로 존재하는 액세스 속성에 관한 것입니다. 이미 말하고있는 (그리고 이미 대부분의 솔루션을 포함하여) 무엇에 관한 질문이 있습니다 : Javascript 중첩 객체에 안전하게 액세스 하거나 string key로 중첩 JavaScript 객체에 액세스하십시오 . 그러나 어쨌든 : "안타깝게도이 방법으로는 중첩 배열에 액세스 할 수 없습니다." 왜 안돼? 배열은 객체이므로 제대로 작동해야합니다. 그렇지 않은 예를 제공 할 수 있습니까?
— Felix Kling

1
@FelixKling Oliver Steele 패턴으로 배열에 액세스하려고하면 '정의되지 않은'오류가 발생하지 않고 'n'길이의 배열을 즉시 생성하고 n 번째 인덱스에 액세스 할 수 없습니다. 전의. ((user || {}).address || new Array(3))[1].name
— Dinesh Pandiyan

3
패턴을 일관되게 적용하지 않습니다. 물론 ...[1].bar요소 1가 존재하지 않으면 오류가 발생 합니다. 하지만 그 또한의 경우의 ....foo.bar경우 foo존재하지 않았다. 1다른 자산 접근을 "보호"하는 것처럼 접근 도 "보호"해야합니다. 배열은 단지 객체입니다. "배열 요소"는 속성 일뿐입니다. 올바르게 적용됩니다 (((user || {}).address || {})[1] || {}).name.
— Felix Kling

1
대단하다. 이런 식으로 나를 때리지 않았다. @FelixKling에게 감사드립니다. 블로그 게시물을 업데이트하겠습니다.
— Dinesh Pandiyan

2
@DineshPandiyan 당신은 당신이 typy의 저자라는 것을 공개해야합니다. 방금 블로그 게시물을 읽은 후 여기에 왔습니다
— reggaeguitar

8

JQuery를 선호합니다. 더 깨끗하고 읽기 쉽습니다.

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

7

다단계 객체에 동적으로 액세스

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

일 바이올린 : https://jsfiddle.net/andreitodorut/3mws3kjL/


6

특정 기준에 맞는 하나 이상의 객체를 찾고 있다면 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:""});

또한 a single와 a가 있으며 각각 singleOrDefault매우 비슷하게 작동 합니다. 유일한 차이점은 더 많은 경우 던질 것입니다firstfirstOrDefault 이상의 일치하는 것이 발견 것입니다.

query-js에 대한 자세한 설명은이 게시물로 시작할 수 있습니다


이것이 어떻게 개선 될 수 있는지 알고 싶습니다. 의견을 남기시겠습니까?
— 룬 FS

6

밑줄 js 방법

functional programming기본 제공 객체를 확장하지 않고도 유용한 도우미를 혼란스럽게 만드는 JavaScript 라이브러리입니다 .

해결책:

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

오래된 질문이지만 아무도 lodash를 언급하지 않았으므로 (밑줄).

프로젝트에서 이미 lodash를 사용하는 경우 복잡한 예에서이를 수행하는 우아한 방법이 있다고 생각합니다.

선택 1

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

다음과 동일

선택 2

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

제 2 옵션 간의 차이점은에 탈퇴 한 에서 오류가 발생하지 않은 경로에 누락 된 (정의되지 않은) 속성 중 하나가 있으면 세 번째 매개 변수를 반환한다는 것입니다.

배열 필터 lodash에는 _.find()있지만 regular을 사용하고 싶습니다 filter(). 그러나 여전히 위의 방법 _.get()은 정말 복잡한 데이터로 작업 할 때 매우 유용 하다고 생각합니다 . 나는 과거에 정말 복잡한 API에 직면했고 편리했습니다!

제목이 암시하는 정말 복잡한 데이터를 조작하는 옵션을 찾는 사람에게 유용 할 수 있기를 바랍니다.


5

나는 질문자가 단지 하나의 레벨 중첩 객체에만 관심이 있다고 생각하지 않으므로 다음 중첩 데모를 제시하여 깊이 중첩 된 json 객체의 노드에 액세스하는 방법을 보여줍니다. 자, 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>


변수를 사용하여 중첩 json 객체에 어떻게 액세스합니까? data = {a : {b : 'ss'}}; var key = ab data [key] 작동하지 않음
— Pasupathi Rajamanickam

3

구문 jsonObject.key을 사용하여 값에 액세스 할 수 있습니다 . 배열에서 값에 액세스하려면 구문을 사용할 수 있습니다 jsonObjectArray[index].key.

아이디어를 제공하기 위해 다양한 값에 액세스하는 코드 예제는 다음과 같습니다.

        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

동적 접근

아래 deep(data,key)함수에서 임의의 key문자열을 사용할 수 있습니다 - 어떤 경우에도 items[1].name배열 표기법 [i]을 사용할 수 있습니다 -키가 유효하지 않으면 undefined가 반환됩니다.


2

임의의 JSON 트리를 풀기위한 파이썬적이고 재귀 적이며 기능적인 접근 방식 :

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)

여기서 데이터 는 파이썬 목록입니다 (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']}
]

6
이 질문은 Python이 아닌 JavaScript에 관한 것입니다. 파이썬과 동등한 질문이 있는지 확실하지 않습니다.
— Felix Kling

2

jQuery의 grep 함수를 사용하면 배열을 통해 필터링 할 수 있습니다.

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

내 stringdataPHP 파일에서 왔지만 여전히 여기에 표시됩니다 var. 내가 직접 내 JSON을 가져갈 때 obj아무것도 내 json 파일을 넣는 이유를 보여주지 않습니다.

var obj=JSON.parse(stringdata); 그래서 그 후 messageobj를 얻고 경고 상자에 표시 한 다음 datajson 배열을 가져 와서 하나의 varible에 저장 한 ArrObj다음이 키 값으로 해당 배열의 첫 번째 객체를 읽습니다.ArrObj[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
stringjson문자열이 아니기 때문에 예제가 혼동 됩니다.
— Felix Kling

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.