중첩 된 객체, 배열 또는 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와 함께varlet,하지만 사용하는 것이 좋습니다 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);

위의 예제 는 외로운 이라는 배열 secondNamename키에서 호출 된 변수를 만듭니다.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.