如何访问和处理嵌套对象,数组或JSON?

发布于 2025-02-13 18:19:56 字数 267 浏览 6 评论 0 原文

我有一个包含对象和数组的嵌套数据结构。如何提取信息,即访问特定或多个值(或密钥)?

例如:

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

如何访问项目中第二个项目的名称

I have a nested data structure containing objects and arrays. How can I extract the information, i.e. access a specific or multiple values (or keys)?

For example:

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

How could I access the name of the second item in items?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(30

挖个坑埋了你 2025-02-20 18:19:57

以防万一,任何人都在2017年或更晚于访问这个问题,并寻找易于回忆的方式,这是

无法读取未定义的错误

1。奥利弗·斯蒂尔(

Steele

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

Oliver 进入

无法读取未定义的的属性“名称”。

您基本上检查用户是否存在,如果不是,则可以随时创建一个空对象。这样,将始终从存在的对象或空对象 中访问下一个级别的密钥,但绝不是从未定义的。

2。使用阵列降低嵌套对象以访问

嵌套数组,您可以编写自己的数组减少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 这一切都适合您。

Just in case, anyone's visiting this question in 2017 or later and looking for an easy-to-remember way, here's an elaborate blog post on Accessing Nested Objects in JavaScript without being bamboozled by

Cannot read property 'foo' of undefined error

1. Oliver Steele's nested object access pattern

The easiest and the cleanest way is to use Oliver Steele's nested object access pattern

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

With this notation, you'll never run into

Cannot read property 'name' of undefined.

You basically check if user exists, if not, you create an empty object on the fly. This way, the next level key will always be accessed from an object that exists or an empty object, but never from undefined.

2. Access Nested Objects Using Array Reduce

To be able to access nested arrays, you can write your own 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.

There is also an excellent type handling minimal library typy that does all this for you.

撩动你心 2025-02-20 18:19:57

如果您愿意包括库:
(node and browser)

https://github.com/s3u/jsonpath 将是:

$..items[1].name

所以:

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

Using JSONPath would be one of the most flexible solutions if you are willing to include a library:
https://github.com/s3u/JSONPath (node and browser)

For your use case the json path would be:

$..items[1].name

so:

var secondName = jsonPath.eval(data, "$..items[1].name");
花想c 2025-02-20 18:19:57

我更喜欢jQuery。它更干净,易于阅读。

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

I prefer JQuery. It's cleaner and easy to read.

$.each($.parseJSON(data), function (key, value) {
  alert(value.<propertyname>);
});
飘然心甜 2025-02-20 18:19:57

如果您正在寻找符合某些条件的一个或多个对象,则使用 query-js < /a>

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

还有一个单个 singleordefault 它们的工作方式非常像 first firstordEfault 。唯一的区别是,如果发现更多的,他们将投掷。

要进一步说明查询-JS,您可以从此 post < /a>

If you are looking for one or more objects that meets certain criteria you have a few options using 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:""});

There's also a single and a singleOrDefault they work much like firstand firstOrDefaultrespectively. The only difference is that they will throw if more than one match is found.

for further explanation of query-js you can start with this post

白龙吟 2025-02-20 18:19:57

下划线JS方式

是一个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);
}

The Underscore js Way

Which is a JavaScript library that provides a whole mess of useful functional programming helpers without extending any built-in objects.

Solution:

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);
}
沫尐诺 2025-02-20 18:19:57

旧问题,但没有人提到洛达什(只是下划线)。

如果您已经在项目中使用了Lodash,我认为在一个复杂的示例中进行了一种优雅的方式:

OPT 1

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

与:

Opt 2

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

第一个第一个之间的区别第二个选项是,在 Opt 1 中,如果您在路径中缺少某种属性(未定义),则不会遇到错误,它将返回第三个参数。

对于数组过滤器,lodash具有_。Find(),但我宁愿使用常规 filter()。但是我仍然认为上面的方法_。get()在使用真正复杂的数据时非常有用。过去,我面对的是非常复杂的API,这很方便!

我希望这对于谁寻找可以操纵标题暗示的真正复杂数据的选项可能会很有用。

Old question but as nobody mentioned lodash (just underscore).

In case you are already using lodash in your project, I think an elegant way to do this in a complex example:

Opt 1

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

same as:

Opt 2

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

The difference between the first and second option is that in the Opt 1 if you have one of the properties missing (undefined) in the path you don't get an error, it returns you the third parameter.

For array filter lodash has _.find() but I'd rather use the regular filter(). But I still think the above method _.get() is super useful when working with really complex data. I faced in the past really complex APIs and it was handy!

I hope it can be useful for who's looking for options to manipulate really complex data which the title implies.

夏天碎花小短裙 2025-02-20 18:19:57

我不认为发问者仅关注一个级别的对象,因此我提出以下演示以演示如何访问深嵌套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>

I don't think questioner just only concern one level nested object, so I present the following demo to demonstrate how to access the node of deeply nested json object. All right, let's find the node with 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>

智商已欠费 2025-02-20 18:19:57

在2020年,您可以使用 @babel/plugin-propopal-optional-optional-Chaining,它很容易访问对象中的嵌套值。

 const obj = {
 foo: {
   bar: {
     baz: class {
   },
  },
 },
};

const baz = new obj?.foo?.bar?.baz(); // baz instance

const safe = new obj?.qux?.baz(); // undefined
const safe2 = new obj?.foo.bar.qux?.(); // undefined

https://babeljs.io/docs/en/babel-babel-babel-plugin-ploposal - 链接

https://github.com/tc39/proposal-optional-chaining

In 2020, you can use @babel/plugin-proposal-optional-chaining it is very easy to access nested values in an object.

 const obj = {
 foo: {
   bar: {
     baz: class {
   },
  },
 },
};

const baz = new obj?.foo?.bar?.baz(); // baz instance

const safe = new obj?.qux?.baz(); // undefined
const safe2 = new obj?.foo.bar.qux?.(); // undefined

https://babeljs.io/docs/en/babel-plugin-proposal-optional-chaining

https://github.com/tc39/proposal-optional-chaining

哭了丶谁疼 2025-02-20 18:19:57

下面的动态方法

deep(数据,密钥)函数,您可以使用任意字符串 - 在情况下 iteg items [1] .name (您可以在任何级别上使用数组符号 [i] ) - 如果键无效,则返回不确定。

let deep = (o,k) => k.split('.').reduce((a,c,i) => {
    let m=c.match(/(.*?)\[(\d*)\]/);
    if(m && a!=null && a[m[1]]!=null) return a[m[1]][+m[2]];
    return a==null ? a: a[c];
},o);

// TEST

let key = 'items[1].name' // arbitrary deep-key

let data = {
    code: 42,
    items: [{ id: 11, name: 'foo'}, { id: 22, name: 'bar'},]
};

console.log( key,'=', deep(data,key) );

Dynamic approach

In below deep(data,key) function, you can use arbitrary key string - in your case items[1].name (you can use array notation [i] at any level) - if key is invalid then undefined is return.

let deep = (o,k) => k.split('.').reduce((a,c,i) => {
    let m=c.match(/(.*?)\[(\d*)\]/);
    if(m && a!=null && a[m[1]]!=null) return a[m[1]][+m[2]];
    return a==null ? a: a[c];
},o);

// TEST

let key = 'items[1].name' // arbitrary deep-key

let data = {
    code: 42,
    items: [{ id: 11, name: 'foo'}, { id: 22, name: 'bar'},]
};

console.log( key,'=', deep(data,key) );

草莓酥 2025-02-20 18:19:57

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>

jQuery's grep function lets you filter through an 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>

天荒地未老 2025-02-20 18:19:57

您可以使用语法 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);

You can use the syntax jsonObject.key to access the the value. And if you want access a value from an array, then you can use the syntax jsonObjectArray[index].key.

Here are the code examples to access various values to give you the idea.

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

倥絔 2025-02-20 18:19:57

这就是我这样做的方式。

 let groups = [
        {
            id:1,
            title:"Group 1",
            members:[
                {
                    id:1,
                    name:"Aftab",
                    battry:'10%'
                },
                {
                    id:2,
                    name:"Jamal",
                },
                {
                    id:3,
                    name:"Hamid",
                },
                {
                    id:4,
                    name:"Aqeel",
                },
            ]
        },
        {
            id:2,
            title:"Group 2",
            members:[
                {
                    id:1,
                    name:"Aftab",
                    battry:'10%'
                },
                {
                    id:2,
                    name:"Jamal",
                    battry:'10%'
                },
                {
                    id:3,
                    name:"Hamid",
                },
               
            ]
        },
        {
            id:3,
            title:"Group 3",
            members:[
                {
                    id:1,
                    name:"Aftab",
                    battry:'10%'
                },
                
                {
                    id:3,
                    name:"Hamid",
                },
                {
                    id:4,
                    name:"Aqeel",
                },
            ]
        }
    ]
    
    groups.map((item) => {
      //  if(item.id == 2){
        item.members.map((element) => {
             if(element.id == 1){
                 element.battry="20%"
             }
         })
        //}
    })
    
    groups.forEach((item) => {
        item.members.forEach((item) => {
            console.log(item)
    })
    })

this is how i have done this.

 let groups = [
        {
            id:1,
            title:"Group 1",
            members:[
                {
                    id:1,
                    name:"Aftab",
                    battry:'10%'
                },
                {
                    id:2,
                    name:"Jamal",
                },
                {
                    id:3,
                    name:"Hamid",
                },
                {
                    id:4,
                    name:"Aqeel",
                },
            ]
        },
        {
            id:2,
            title:"Group 2",
            members:[
                {
                    id:1,
                    name:"Aftab",
                    battry:'10%'
                },
                {
                    id:2,
                    name:"Jamal",
                    battry:'10%'
                },
                {
                    id:3,
                    name:"Hamid",
                },
               
            ]
        },
        {
            id:3,
            title:"Group 3",
            members:[
                {
                    id:1,
                    name:"Aftab",
                    battry:'10%'
                },
                
                {
                    id:3,
                    name:"Hamid",
                },
                {
                    id:4,
                    name:"Aqeel",
                },
            ]
        }
    ]
    
    groups.map((item) => {
      //  if(item.id == 2){
        item.members.map((element) => {
             if(element.id == 1){
                 element.battry="20%"
             }
         })
        //}
    })
    
    groups.forEach((item) => {
        item.members.forEach((item) => {
            console.log(item)
    })
    })
温柔戏命师 2025-02-20 18:19:57

如果您试图在JSON字符串中找到路径,则可以将数据倒入工具中以确定您的路径。

当您在嵌套的JS对象结构中徘徊在它们上时,Chrome Developer Console将显示属性路径,可以使用 JSON.PARSE(JSON)在必要时从JSON中解析

。 /I.SSTATIC.NET/1H3RH.PNG“ rel =” nofollow noreferrer“> “

您也可以将路径复制到剪贴板:

noreferrer“> ” [0] 替换偏移索引来迭代数组 环形。然后,您可以在其位置使用循环索引 [i] ,也可以使用 foreach 样式函数替换整个属性和索引。

另一个工具是 https://jsonpathfinder.com 您可以在其中单击GUI元素。它将为像chrome一样的路径生成JS语法。

我写了一个简单的工具,您可以在这里或 https://ggorlen.github.io/json -Dive/。将JSON字符串粘贴到Textarea中,然后单击节点将其路径复制到剪贴板。它可以选择使用括号而不是点生成Python/PHP样式索引。

/* code minified to make the tool easier to run without having to scroll */                                                         let bracketsOnly=!1,lastHighlighted={style:{}};const keyToStr=t=>!bracketsOnly&&/^[a-zA-Z_$][a-zA-Z$_\d]*$/.test(t)?`.${toHTML(t)}`:`["${toHTML(t)}"]`,pathToData=t=>`data-path="data${t.join("")}"`,htmlSpecialChars={"&":"&","<":"<",">":">",'"':""","'":"'","\t":"\\t","\r":"\\r","\n":"\\n"," ":" "},toHTML=t=>(""+t).replace(/[&<>"'\t\r\n ]/g,t=>htmlSpecialChars[t]),makeArray=(t,e)=>`\n  [<ul ${pathToData(e)}>\n    ${t.map((t,a)=>{e.push(`[${a}]`);const n=`<li ${pathToData(e)}>\n        ${pathify(t,e).trim()},\n      </li>`;return e.pop(),n}).join("")}\n  </ul>]\n`,makeObj=(t,e)=>`\n  {<ul ${pathToData(e)}>\n    ${Object.entries(t).map(([t,a])=>{e.push(keyToStr(t));const n=`<li ${pathToData(e)}>\n        "${toHTML(t)}": ${pathify(a,e).trim()},\n      </li>`;return e.pop(),n}).join("")}\n  </ul>}\n`,pathify=(t,e=[])=>Array.isArray(t)?makeArray(t,e):"object"==typeof t&&t!=null?makeObj(t,e):toHTML("string"==typeof t?`"${t}"`:t),defaultJSON='{\n  "corge": "test JSON... \\n   asdf\\t asdf",\n  "foo-bar": [\n    {"id": 42},\n    [42, {"foo": {"baz": {"ba  r<>!\\t": true, "4quux": "garply"}}}]\n  ]\n}',$=document.querySelector.bind(document),$=document.querySelectorAll.bind(document),resultEl=$("#result"),pathEl=$("#path"),tryToJSON=t=>{try{resultEl.innerHTML=pathify(JSON.parse(t)),$("#error").innerText=""}catch(t){resultEl.innerHTML="",$("#error").innerText=t}},copyToClipboard=t=>{const e=document.createElement("textarea");e.textContent=t,document.body.appendChild(e),e.select(),document.execCommand("copy"),document.body.removeChild(e)},flashAlert=(t,e=2e3)=>{const a=document.createElement("div");a.textContent=t,a.classList.add("alert"),document.body.appendChild(a),setTimeout(()=>a.remove(),e)},handleClick=t=>{t.stopPropagation(),copyToClipboard(t.target.dataset.path),flashAlert("copied!"),$("#path-out").textContent=t.target.dataset.path},handleMouseOut=t=>{lastHighlighted.style.background="transparent",pathEl.style.display="none"},handleMouseOver=t=>{pathEl.textContent=t.target.dataset.path,pathEl.style.left=`${t.pageX+30}px`,pathEl.style.top=`${t.pageY}px`,pathEl.style.display="block",lastHighlighted.style.background="transparent",(lastHighlighted=t.target.closest("li")).style.background="#0ff"},handleNewJSON=t=>{tryToJSON(t.target.value),[...$("#result *")].forEach(t=>{t.addEventListener("click",handleClick),t.addEventListener("mouseout",handleMouseOut),t.addEventListener("mouseover",handleMouseOver)})};$("textarea").addEventListener("change",handleNewJSON),$("textarea").addEventListener("keyup",handleNewJSON),$("textarea").value=defaultJSON,$("#brackets").addEventListener("change",t=>{bracketsOnly=!bracketsOnly,handleNewJSON({target:{value:$("textarea").value}})}),handleNewJSON({target:{value:defaultJSON}});
/**/                                                                                       *{box-sizing:border-box;font-family:monospace;margin:0;padding:0}html{height:100%}#path-out{background-color:#0f0;padding:.3em}body{margin:0;height:100%;position:relative;background:#f8f8f8}textarea{width:100%;height:110px;resize:vertical}#opts{background:#e8e8e8;padding:.3em}#opts label{padding:.3em}#path{background:#000;transition:all 50ms;color:#fff;padding:.2em;position:absolute;display:none}#error{margin:.5em;color:red}#result ul{list-style:none}#result li{cursor:pointer;border-left:1em solid transparent}#result li:hover{border-color:#ff0}.alert{background:#f0f;padding:.2em;position:fixed;bottom:10px;right:10px}
<!-- -->                                                                                                    <div class="wrapper"><textarea></textarea><div id="opts"><label>brackets only: <input id="brackets"type="checkbox"></label></div><div id="path-out">click a node to copy path to clipboard</div><div id="path"></div><div id="result"></div><div id="error"></div></div>

未经许可(也可以在 github ):

let bracketsOnly = false;
let lastHighlighted = {style: {}};

const keyToStr = k =>
  !bracketsOnly && /^[a-zA-Z_$][a-zA-Z$_\d]*$/.test(k) 
    ? `.${toHTML(k)}`
    : `["${toHTML(k)}"]`
;
const pathToData = p => `data-path="data${p.join("")}"`;

const htmlSpecialChars = {
  "&": "&",
  "<": "<",
  ">": ">",
  '"': """,
  "'": "'",
  "\t": "\\t",
  "\r": "\\r",
  "\n": "\\n",
  " ": " ",
};
const toHTML = x => ("" + x)
  .replace(/[&<>"'\t\r\n ]/g, m => htmlSpecialChars[m])
;

const makeArray = (x, path) => `
  [<ul ${pathToData(path)}>
    ${x.map((e, i) => {
      path.push(`[${i}]`);
      const html = `<li ${pathToData(path)}>
        ${pathify(e, path).trim()},
      </li>`;
      path.pop();
      return html;
    }).join("")}
  </ul>]
`;
const makeObj = (x, path) => `
  {<ul ${pathToData(path)}>
    ${Object.entries(x).map(([k, v]) => {
      path.push(keyToStr(k));
      const html = `<li ${pathToData(path)}>
        "${toHTML(k)}": ${pathify(v, path).trim()},
      </li>`;
      path.pop();
      return html;
    }).join("")}
  </ul>}
`;

const pathify = (x, path=[]) => {
  if (Array.isArray(x)) {
    return makeArray(x, path);
  }
  else if (typeof x === "object" && x !== null) {
    return makeObj(x, path);
  }
  
  return toHTML(typeof x === "string" ? `"${x}"` : x);
};

const defaultJSON = `{
  "corge": "test JSON... \\n   asdf\\t asdf",
  "foo-bar": [
    {"id": 42},
    [42, {"foo": {"baz": {"ba  r<>!\\t": true, "4quux": "garply"}}}]
  ]
}`;

const $ = document.querySelector.bind(document);
const $ = document.querySelectorAll.bind(document);
const resultEl = $("#result");
const pathEl = $("#path");

const tryToJSON = v => {
  try {
    resultEl.innerHTML = pathify(JSON.parse(v));
    $("#error").innerText = "";
  }
  catch (err) {
    resultEl.innerHTML = "";
    $("#error").innerText = err;
  }
};

const copyToClipboard = text => {
  const ta = document.createElement("textarea");
  ta.textContent = text;
  document.body.appendChild(ta);
  ta.select();
  document.execCommand("copy");
  document.body.removeChild(ta);
};

const flashAlert = (text, timeoutMS=2000) => {
  const alert = document.createElement("div");
  alert.textContent = text;
  alert.classList.add("alert");
  document.body.appendChild(alert);
  setTimeout(() => alert.remove(), timeoutMS);
};

const handleClick = e => {
  e.stopPropagation();
  copyToClipboard(e.target.dataset.path);
  flashAlert("copied!");
  $("#path-out").textContent = e.target.dataset.path;
};

const handleMouseOut = e => {
  lastHighlighted.style.background = "transparent";
  pathEl.style.display = "none";
};

const handleMouseOver = e => {
  pathEl.textContent = e.target.dataset.path;
  pathEl.style.left = `${e.pageX + 30}px`;
  pathEl.style.top = `${e.pageY}px`;
  pathEl.style.display = "block";
  lastHighlighted.style.background = "transparent";
  lastHighlighted = e.target.closest("li");
  lastHighlighted.style.background = "#0ff";
};

const handleNewJSON = e => {
  tryToJSON(e.target.value);
  [...$("#result *")].forEach(e => {
    e.addEventListener("click", handleClick);
    e.addEventListener("mouseout", handleMouseOut);
    e.addEventListener("mouseover", handleMouseOver);
  });
};
$("textarea").addEventListener("change", handleNewJSON);
$("textarea").addEventListener("keyup", handleNewJSON);
$("textarea").value = defaultJSON;
$("#brackets").addEventListener("change", e => {
  bracketsOnly = !bracketsOnly;
  handleNewJSON({target: {value: $("textarea").value}});
});
handleNewJSON({target: {value: defaultJSON}});
* {
  box-sizing: border-box;
  font-family: monospace;
  margin: 0;
  padding: 0;
}

html {
  height: 100%;
}

#path-out {
  background-color: #0f0;
  padding: 0.3em;
}

body {
  margin: 0;
  height: 100%;
  position: relative;
  background: #f8f8f8;
}

textarea {
  width: 100%;
  height: 110px;
  resize: vertical;
}

#opts {
  background: #e8e8e8;
  padding: 0.3em;
}
#opts label {
  padding: 0.3em;
}

#path {
  background: black;
  transition: all 0.05s;
  color: white;
  padding: 0.2em;
  position: absolute;
  display: none;
}

#error {
  margin: 0.5em;
  color: red;
}

#result ul {
  list-style: none;
}

#result li {
  cursor: pointer;
  border-left: 1em solid transparent;
}
#result li:hover {
  border-color: #ff0;
}

.alert {
  background: #f0f;
  padding: 0.2em;
  position: fixed;
  bottom: 10px;
  right: 10px;
}
<div class="wrapper">
  <textarea></textarea>
  <div id="opts">
    <label>
      brackets only: <input id="brackets" type="checkbox">
    </label>
  </div>
  <div id="path-out">click a node to copy path to clipboard</div>
  <div id="path"></div>
  <div id="result"></div>
  <div id="error"></div>
</div>

这并不是要替代学习如何钓鱼,但是一旦您知道,就可以节省时间。

If you're trying to find a path in a JSON string, you can dump your data into a tool to determine the path for you.

The Chrome developer console shows property paths when you hover over them in a nested JS object structure, which can be parsed from JSON using JSON.parse(json) if necessary:

chrome console hovering an object key shows the path to get there on hover

You can also copy the path to the clipboard:

chrome console about to copy property path for object to clipboard using the context menu on a node

Once you have a path on the clipboard, you will typically want to iterate arrays by replacing the offset indexers like [0] with a loop. You can then use the loop index [i] in its place, or use a forEach style function to replace the whole property and index.

Another tool is https://jsonpathfinder.com where you can click on the GUI elements. It'll generate the JS syntax for the path to the element like Chrome.

I wrote a simple tool you can run here, or at https://ggorlen.github.io/json-dive/. Paste your JSON string into the textarea, then click the node to copy its path to your clipboard. It has an option to generate Python/PHP style indexes with brackets rather than dots.

/* code minified to make the tool easier to run without having to scroll */                                                         let bracketsOnly=!1,lastHighlighted={style:{}};const keyToStr=t=>!bracketsOnly&&/^[a-zA-Z_$][a-zA-Z$_\d]*$/.test(t)?`.${toHTML(t)}`:`["${toHTML(t)}"]`,pathToData=t=>`data-path="data${t.join("")}"`,htmlSpecialChars={"&":"&","<":"<",">":">",'"':""","'":"'","\t":"\\t","\r":"\\r","\n":"\\n"," ":" "},toHTML=t=>(""+t).replace(/[&<>"'\t\r\n ]/g,t=>htmlSpecialChars[t]),makeArray=(t,e)=>`\n  [<ul ${pathToData(e)}>\n    ${t.map((t,a)=>{e.push(`[${a}]`);const n=`<li ${pathToData(e)}>\n        ${pathify(t,e).trim()},\n      </li>`;return e.pop(),n}).join("")}\n  </ul>]\n`,makeObj=(t,e)=>`\n  {<ul ${pathToData(e)}>\n    ${Object.entries(t).map(([t,a])=>{e.push(keyToStr(t));const n=`<li ${pathToData(e)}>\n        "${toHTML(t)}": ${pathify(a,e).trim()},\n      </li>`;return e.pop(),n}).join("")}\n  </ul>}\n`,pathify=(t,e=[])=>Array.isArray(t)?makeArray(t,e):"object"==typeof t&&t!=null?makeObj(t,e):toHTML("string"==typeof t?`"${t}"`:t),defaultJSON='{\n  "corge": "test JSON... \\n   asdf\\t asdf",\n  "foo-bar": [\n    {"id": 42},\n    [42, {"foo": {"baz": {"ba  r<>!\\t": true, "4quux": "garply"}}}]\n  ]\n}',$=document.querySelector.bind(document),$=document.querySelectorAll.bind(document),resultEl=$("#result"),pathEl=$("#path"),tryToJSON=t=>{try{resultEl.innerHTML=pathify(JSON.parse(t)),$("#error").innerText=""}catch(t){resultEl.innerHTML="",$("#error").innerText=t}},copyToClipboard=t=>{const e=document.createElement("textarea");e.textContent=t,document.body.appendChild(e),e.select(),document.execCommand("copy"),document.body.removeChild(e)},flashAlert=(t,e=2e3)=>{const a=document.createElement("div");a.textContent=t,a.classList.add("alert"),document.body.appendChild(a),setTimeout(()=>a.remove(),e)},handleClick=t=>{t.stopPropagation(),copyToClipboard(t.target.dataset.path),flashAlert("copied!"),$("#path-out").textContent=t.target.dataset.path},handleMouseOut=t=>{lastHighlighted.style.background="transparent",pathEl.style.display="none"},handleMouseOver=t=>{pathEl.textContent=t.target.dataset.path,pathEl.style.left=`${t.pageX+30}px`,pathEl.style.top=`${t.pageY}px`,pathEl.style.display="block",lastHighlighted.style.background="transparent",(lastHighlighted=t.target.closest("li")).style.background="#0ff"},handleNewJSON=t=>{tryToJSON(t.target.value),[...$("#result *")].forEach(t=>{t.addEventListener("click",handleClick),t.addEventListener("mouseout",handleMouseOut),t.addEventListener("mouseover",handleMouseOver)})};$("textarea").addEventListener("change",handleNewJSON),$("textarea").addEventListener("keyup",handleNewJSON),$("textarea").value=defaultJSON,$("#brackets").addEventListener("change",t=>{bracketsOnly=!bracketsOnly,handleNewJSON({target:{value:$("textarea").value}})}),handleNewJSON({target:{value:defaultJSON}});
/**/                                                                                       *{box-sizing:border-box;font-family:monospace;margin:0;padding:0}html{height:100%}#path-out{background-color:#0f0;padding:.3em}body{margin:0;height:100%;position:relative;background:#f8f8f8}textarea{width:100%;height:110px;resize:vertical}#opts{background:#e8e8e8;padding:.3em}#opts label{padding:.3em}#path{background:#000;transition:all 50ms;color:#fff;padding:.2em;position:absolute;display:none}#error{margin:.5em;color:red}#result ul{list-style:none}#result li{cursor:pointer;border-left:1em solid transparent}#result li:hover{border-color:#ff0}.alert{background:#f0f;padding:.2em;position:fixed;bottom:10px;right:10px}
<!-- -->                                                                                                    <div class="wrapper"><textarea></textarea><div id="opts"><label>brackets only: <input id="brackets"type="checkbox"></label></div><div id="path-out">click a node to copy path to clipboard</div><div id="path"></div><div id="result"></div><div id="error"></div></div>

Unminified (also available on GitHub):

let bracketsOnly = false;
let lastHighlighted = {style: {}};

const keyToStr = k =>
  !bracketsOnly && /^[a-zA-Z_$][a-zA-Z$_\d]*$/.test(k) 
    ? `.${toHTML(k)}`
    : `["${toHTML(k)}"]`
;
const pathToData = p => `data-path="data${p.join("")}"`;

const htmlSpecialChars = {
  "&": "&",
  "<": "<",
  ">": ">",
  '"': """,
  "'": "'",
  "\t": "\\t",
  "\r": "\\r",
  "\n": "\\n",
  " ": " ",
};
const toHTML = x => ("" + x)
  .replace(/[&<>"'\t\r\n ]/g, m => htmlSpecialChars[m])
;

const makeArray = (x, path) => `
  [<ul ${pathToData(path)}>
    ${x.map((e, i) => {
      path.push(`[${i}]`);
      const html = `<li ${pathToData(path)}>
        ${pathify(e, path).trim()},
      </li>`;
      path.pop();
      return html;
    }).join("")}
  </ul>]
`;
const makeObj = (x, path) => `
  {<ul ${pathToData(path)}>
    ${Object.entries(x).map(([k, v]) => {
      path.push(keyToStr(k));
      const html = `<li ${pathToData(path)}>
        "${toHTML(k)}": ${pathify(v, path).trim()},
      </li>`;
      path.pop();
      return html;
    }).join("")}
  </ul>}
`;

const pathify = (x, path=[]) => {
  if (Array.isArray(x)) {
    return makeArray(x, path);
  }
  else if (typeof x === "object" && x !== null) {
    return makeObj(x, path);
  }
  
  return toHTML(typeof x === "string" ? `"${x}"` : x);
};

const defaultJSON = `{
  "corge": "test JSON... \\n   asdf\\t asdf",
  "foo-bar": [
    {"id": 42},
    [42, {"foo": {"baz": {"ba  r<>!\\t": true, "4quux": "garply"}}}]
  ]
}`;

const $ = document.querySelector.bind(document);
const $ = document.querySelectorAll.bind(document);
const resultEl = $("#result");
const pathEl = $("#path");

const tryToJSON = v => {
  try {
    resultEl.innerHTML = pathify(JSON.parse(v));
    $("#error").innerText = "";
  }
  catch (err) {
    resultEl.innerHTML = "";
    $("#error").innerText = err;
  }
};

const copyToClipboard = text => {
  const ta = document.createElement("textarea");
  ta.textContent = text;
  document.body.appendChild(ta);
  ta.select();
  document.execCommand("copy");
  document.body.removeChild(ta);
};

const flashAlert = (text, timeoutMS=2000) => {
  const alert = document.createElement("div");
  alert.textContent = text;
  alert.classList.add("alert");
  document.body.appendChild(alert);
  setTimeout(() => alert.remove(), timeoutMS);
};

const handleClick = e => {
  e.stopPropagation();
  copyToClipboard(e.target.dataset.path);
  flashAlert("copied!");
  $("#path-out").textContent = e.target.dataset.path;
};

const handleMouseOut = e => {
  lastHighlighted.style.background = "transparent";
  pathEl.style.display = "none";
};

const handleMouseOver = e => {
  pathEl.textContent = e.target.dataset.path;
  pathEl.style.left = `${e.pageX + 30}px`;
  pathEl.style.top = `${e.pageY}px`;
  pathEl.style.display = "block";
  lastHighlighted.style.background = "transparent";
  lastHighlighted = e.target.closest("li");
  lastHighlighted.style.background = "#0ff";
};

const handleNewJSON = e => {
  tryToJSON(e.target.value);
  [...$("#result *")].forEach(e => {
    e.addEventListener("click", handleClick);
    e.addEventListener("mouseout", handleMouseOut);
    e.addEventListener("mouseover", handleMouseOver);
  });
};
$("textarea").addEventListener("change", handleNewJSON);
$("textarea").addEventListener("keyup", handleNewJSON);
$("textarea").value = defaultJSON;
$("#brackets").addEventListener("change", e => {
  bracketsOnly = !bracketsOnly;
  handleNewJSON({target: {value: $("textarea").value}});
});
handleNewJSON({target: {value: defaultJSON}});
* {
  box-sizing: border-box;
  font-family: monospace;
  margin: 0;
  padding: 0;
}

html {
  height: 100%;
}

#path-out {
  background-color: #0f0;
  padding: 0.3em;
}

body {
  margin: 0;
  height: 100%;
  position: relative;
  background: #f8f8f8;
}

textarea {
  width: 100%;
  height: 110px;
  resize: vertical;
}

#opts {
  background: #e8e8e8;
  padding: 0.3em;
}
#opts label {
  padding: 0.3em;
}

#path {
  background: black;
  transition: all 0.05s;
  color: white;
  padding: 0.2em;
  position: absolute;
  display: none;
}

#error {
  margin: 0.5em;
  color: red;
}

#result ul {
  list-style: none;
}

#result li {
  cursor: pointer;
  border-left: 1em solid transparent;
}
#result li:hover {
  border-color: #ff0;
}

.alert {
  background: #f0f;
  padding: 0.2em;
  position: fixed;
  bottom: 10px;
  right: 10px;
}
<div class="wrapper">
  <textarea></textarea>
  <div id="opts">
    <label>
      brackets only: <input id="brackets" type="checkbox">
    </label>
  </div>
  <div id="path-out">click a node to copy path to clipboard</div>
  <div id="path"></div>
  <div id="result"></div>
  <div id="error"></div>
</div>

This isn't intended as a substitute for learning how to fish but can save time once you do know.

巷雨优美回忆 2025-02-20 18:19:57
// 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;
}
// 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;
}
望喜 2025-02-20 18:19:57

这是使用 object-scan 的答案。

访问单个条目时,此答案实际上并没有比Vanilla JavaScript提供太大的好处。但是,同时与多个字段进行互动,此答案可能更具性能。

这是您可以与单个字段互动的方式

// const objectScan = require('object-scan');

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

const get = (haystack, needle) => objectScan([needle], {
  abort: true,
  rtn: 'value'
})(haystack);

const set = (haystack, needle, value) => objectScan([needle], {
  abort: true,
  rtn: 'bool',
  filterFn: ({ parent, property }) => {
    parent[property] = value;
    return true;
  }
})(haystack);

console.log(get(data, 'items[1].name'));
// => bar

console.log(set(data, 'items[1].name', 'foo2'));
// => true
console.log(data);
// => { code: 42, items: [ { id: 1, name: 'foo' }, { id: 2, name: 'foo2' } ] }
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/[email protected]"></script>

免责声明:我是 object-scan 的作者

这是您可以同时与多个字段互动的方式

// const objectScan = require('object-scan');

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

const get = (haystack, ...needles) => objectScan(needles, {
  joined: true,
  rtn: 'entry'
})(haystack);

const set = (haystack, actions) => objectScan(Object.keys(actions), {
  rtn: 'count',
  filterFn: ({ matchedBy, parent, property }) => {
    matchedBy.forEach((m) => {
      parent[property] = actions[m];
    })
    return true;
  }
})(haystack);

console.log(get(data, 'items[0].name', 'items[1].name'));
// => [ [ 'items[1].name', 'bar' ], [ 'items[0].name', 'foo' ] ]

console.log(set(data, {
  'items[0].name': 'foo1',
  'items[1].name': 'foo2'
}));
// => 2
console.log(data);
// => { code: 42, items: [ { id: 1, name: 'foo1' }, { id: 2, name: 'foo2' } ] }
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/[email protected]"></script>

免责声明:我是 object-scan 的作者


这是人们如何在通过ID搜索的深度嵌套对象中找到一个实体(如评论中所要求)

// const objectScan = require('object-scan');

const myData = { 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' }] }] };

const findItemById = (haystack, id) => objectScan(['**(^items$).id'], {
  abort: true,
  useArraySelector: false,
  rtn: 'parent',
  filterFn: ({ value }) => value === id
})(haystack);

console.log(findItemById(myData, 5));
// => { id: 5, name: 'eee' }
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/[email protected]"></script>

免责声明:我是 object-scan 的作者

Here is an answer using object-scan.

When accessing a single entry, this answer doesn't really provide much benefit over vanilla javascript. However interacting with multiple fields at the same time this answer can be more performant.

Here is how you could interact with a single field

// const objectScan = require('object-scan');

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

const get = (haystack, needle) => objectScan([needle], {
  abort: true,
  rtn: 'value'
})(haystack);

const set = (haystack, needle, value) => objectScan([needle], {
  abort: true,
  rtn: 'bool',
  filterFn: ({ parent, property }) => {
    parent[property] = value;
    return true;
  }
})(haystack);

console.log(get(data, 'items[1].name'));
// => bar

console.log(set(data, 'items[1].name', 'foo2'));
// => true
console.log(data);
// => { code: 42, items: [ { id: 1, name: 'foo' }, { id: 2, name: 'foo2' } ] }
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/[email protected]"></script>

Disclaimer: I'm the author of object-scan

and here is how you could interact with multiple fields at the same time

// const objectScan = require('object-scan');

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

const get = (haystack, ...needles) => objectScan(needles, {
  joined: true,
  rtn: 'entry'
})(haystack);

const set = (haystack, actions) => objectScan(Object.keys(actions), {
  rtn: 'count',
  filterFn: ({ matchedBy, parent, property }) => {
    matchedBy.forEach((m) => {
      parent[property] = actions[m];
    })
    return true;
  }
})(haystack);

console.log(get(data, 'items[0].name', 'items[1].name'));
// => [ [ 'items[1].name', 'bar' ], [ 'items[0].name', 'foo' ] ]

console.log(set(data, {
  'items[0].name': 'foo1',
  'items[1].name': 'foo2'
}));
// => 2
console.log(data);
// => { code: 42, items: [ { id: 1, name: 'foo1' }, { id: 2, name: 'foo2' } ] }
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/[email protected]"></script>

Disclaimer: I'm the author of object-scan


And here is how one could find an entity in a deeply nested object searching by id (as asked in comment)

// const objectScan = require('object-scan');

const myData = { 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' }] }] };

const findItemById = (haystack, id) => objectScan(['**(^items$).id'], {
  abort: true,
  useArraySelector: false,
  rtn: 'parent',
  filterFn: ({ value }) => value === id
})(haystack);

console.log(findItemById(myData, 5));
// => { id: 5, name: 'eee' }
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/[email protected]"></script>

Disclaimer: I'm the author of object-scan

┈┾☆殇 2025-02-20 18:19:57

您需要做的事情真的很简单,并且可以实现潮流率:

const json_object = {
        "item1":{
            "name": "apple",
            "value": 2,
        },
        "item2":{
            "name": "pear",
            "value": 4,
        },
        "item3":{
            "name": "mango",
            "value": 3,
            "prices": {
                "1": "9$",
                "2": "59$",
                "3": "1$"
            }
        }
    }
    
    function walkJson(json_object){
        for(obj in json_object){
            if(typeof json_object[obj] === 'string'){
                console.log(`${obj}=>${json_object[obj]}`);
            }else{
                console.log(`${obj}=>${json_object[obj]}`);
                walkJson(json_object[obj]);
            }
        }           
    }
    
    walkJson(json_object);

what you need to do is really simple and it can be achieved trough recursivity:

const json_object = {
        "item1":{
            "name": "apple",
            "value": 2,
        },
        "item2":{
            "name": "pear",
            "value": 4,
        },
        "item3":{
            "name": "mango",
            "value": 3,
            "prices": {
                "1": "9
quot;,
                "2": "59
quot;,
                "3": "1
quot;
            }
        }
    }
    
    function walkJson(json_object){
        for(obj in json_object){
            if(typeof json_object[obj] === 'string'){
                console.log(`${obj}=>${json_object[obj]}`);
            }else{
                console.log(`${obj}=>${json_object[obj]}`);
                walkJson(json_object[obj]);
            }
        }           
    }
    
    walkJson(json_object);
玩套路吗 2025-02-20 18:19:57

一种pythonic,递归和功能性方法来解开任意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)

其中 data 是python列表(根据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']}
]

A pythonic, recursive and functional approach to unravel arbitrary JSON trees:

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)

where data is a python list (parsed from a JSON text string):

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']}
]
小情绪 2025-02-20 18:19:57

我的 StringData 来自PHP文件,但我仍然在此处注明 var 。当我将JSON直接带入 obj 时,它将没有显示为什么我将json文件放在

var obj = json.parse(stringdata); >
因此,之后,我得到消息 obj并在警报框中显示,然后我获得数据是JSON数组,然后存储在一个可变量 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);
            

My stringdata is coming from PHP file but still, I indicate here in var. When i directly take my json into obj it will nothing show thats why i put my json file as

var obj=JSON.parse(stringdata);
so after that i get message obj and show in alert box then I get data which is json array and store in one varible ArrObj then i read first object of that array with key value like this 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);
            
心欲静而疯不止 2025-02-20 18:19:56

预段

JavaScript只有一种数据类型,该数据类型可以包含多个值:对象数组是一种特殊形式。

(平原)对象具有

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

表单数组的形式,既有

[value, value, ...]

数组和对象露出键 - &gt;值结构。数组中的键必须是数字,而任何字符串都可以用作对象中的键。钥匙值对也称为“属性”

可以使用 dot表示法

const value = obj.someProperty;

括号符号访问属性,如果属性名称不是有效的javascript 标识符名称​​ [spec] ,否则名称是值一个变量:

// 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数据类型,即数组和对象(以及如何与这些对象一起使用)。在问题 javascript中解析JSON?中。

进一步读取材料

如何访问阵列和对象是基本的JavaScript知识,因此建议阅读 MDN JavaScript指南,尤其是部分



访问嵌套的数据结构

嵌套数据结构是一个数组或对象,它是指其他数组或对象,即其值是数组或对象。可以连续应用点或括号表示法访问此类结构。

这是一个示例:

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

假设我们要访问第二项的名称

这是我们可以逐步完成的方法:

正如我们可以看到数据是一个对象,因此我们可以使用点表示法访问其属性。 项目属性被访问如下:

data.items

值是一个数组,要访问其第二个元素,我们必须使用括号符号:

data.items[1]

此值是一个对象,我们再次使用点符号来访问名称属性。因此,我们最终得到:

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

或者,我们本可以为任何属性使用括号符号,尤其是当名称包含字符而使DOT符号用法无效的字符:

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

我正在尝试访问属性,但我只会得到未定义的返回?

在大多数情况下,当您获得未定义的时,对象/数组根本没有该名称的属性。

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

使用 console.log 或< a href =“ https://developer.mozilla.org/en-us/docs/dom/console.dir” rel =“ noreferrer”> console.dir 并检查对象/数组的结构。您要访问的属性实际上可能是在嵌套对象 /数组上定义的。

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

如果属性名称是动态的,而我不知道它们怎么办?

如果属性名称未知或我们要访问数组的对象/元素的所有属性,我们可以使用 for ... in [mdn] 对象的循环和 的代码> [MDN] 循环以迭代所有属性/元素。

对象

要迭代 data 的所有属性,我们可以通过 object 这样的迭代:

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
}

取决于对象的来源(以及您的内容)想要这样做),您可能必须在每次迭代中测试该属性是真正的属性,还是它是继承的属性。您可以使用 [MDN]

作为 in hasownProperty 的替代方案,您可以使用 object.keys.keys [mdn] 获得属性名称

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

数组

data.items array ,我们使用循环的

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 迭代阵列,但是那里这是应避免这种情况的原因:为什么'对于(列表中的var item)'在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)的环境中,您也可以使用 for ... of [mdn] loop,仅适用于数组,但对于任何

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

href 迭代,直接为我们提供了峰值的下一个元素,没有访问或使用的“索引”。


如果我不知道数据结构的“深度”怎么办?

除了未知键外,数据结构的“深度”(即它具有多少个嵌套对象)也可能未知。如何访问深嵌套的属性通常取决于确切的数据结构。

但是,如果数据结构包含重复模式,例如二进制树的表示,则该解决方案通常包括 递归 [Wikipedia] 访问数据结构的每个级别。

这是获取二进制树的第一个叶子节点的示例:

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

const root = {
    leftChild: {
        leftChild: {
            leftChild: null,
            rightChild: null,
            data: 42
        },
        rightChild: {
            leftChild: null,
            rightChild: null,
            data: 5
        }
    },
    rightChild: {
        leftChild: {
            leftChild: null,
            rightChild: null,
            data: 6
        },
        rightChild: {
            leftChild: null,
            rightChild: null,
            data: 7
        }
    }
};
function getLeaf(node) {
    if (node.leftChild) {
        return getLeaf(node.leftChild);
    } else if (node.rightChild) {
        return getLeaf(node.rightChild);
    } else { // node must be a leaf node
        return node;
    }
}

console.log(getLeaf(root).data);

使用未知密钥和深度访问嵌套数据结构的一种更通用的方法是测试值的类型并相应地行动。

这是一个示例,该示例将嵌套数据结构中的所有原始值添加到数组中(假设它不包含任何功能)。如果我们遇到一个对象(或数组),我们只需在该值(递归调用)上再次调用 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;
}

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


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

console.log(toArray(data));



助手

由于复杂对象或数组的结构不一定是显而易见的,因此我们可以在每个步骤中检查值以决定如何进一步移动。 console.log [[ mdn] console.dir [mdn] 帮助我们这样做。例如(Chrome Console的输出):

> 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> id name __ Proto __ 。后者是用于对象的原型链的内部属性。但是,原型链和继承的范围不超出此答案的范围。

Preliminaries

JavaScript has only one data type which can contain multiple values: Object. An Array is a special form of object.

(Plain) Objects have the form

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

Arrays have the form

[value, value, ...]

Both arrays and objects expose a key -> value structure. Keys in an array must be numeric, whereas any string can be used as key in objects. The key-value pairs are also called the "properties".

Properties can be accessed either using dot notation

const value = obj.someProperty;

or bracket notation, if the property name would not be a valid JavaScript identifier name [spec], or the name is the value of a variable:

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

For that reason, array elements can only be accessed using bracket notation:

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

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

Wait... what about JSON?

JSON is a textual representation of data, just like XML, YAML, CSV, and others. To work with such data, it first has to be converted to JavaScript data types, i.e. arrays and objects (and how to work with those was just explained). How to parse JSON is explained in the question Parse JSON in JavaScript? .

Further reading material

How to access arrays and objects is fundamental JavaScript knowledge and therefore it is advisable to read the MDN JavaScript Guide, especially the sections



Accessing nested data structures

A nested data structure is an array or object which refers to other arrays or objects, i.e. its values are arrays or objects. Such structures can be accessed by consecutively applying dot or bracket notation.

Here is an example:

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

Let's assume we want to access the name of the second item.

Here is how we can do it step-by-step:

As we can see data is an object, hence we can access its properties using dot notation. The items property is accessed as follows:

data.items

The value is an array, to access its second element, we have to use bracket notation:

data.items[1]

This value is an object and we use dot notation again to access the name property. So we eventually get:

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

Alternatively, we could have used bracket notation for any of the properties, especially if the name contained characters that would have made it invalid for dot notation usage:

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

I'm trying to access a property but I get only undefined back?

Most of the time when you are getting undefined, the object/array simply doesn't have a property with that name.

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

Use console.log or console.dir and inspect the structure of object / array. The property you are trying to access might be actually defined on a nested object / array.

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

What if the property names are dynamic and I don't know them beforehand?

If the property names are unknown or we want to access all properties of an object / elements of an array, we can use the for...in [MDN] loop for objects and the for [MDN] loop for arrays to iterate over all properties / elements.

Objects

To iterate over all properties of data, we can iterate over the object like so:

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
}

Depending on where the object comes from (and what you want to do), you might have to test in each iteration whether the property is really a property of the object, or it is an inherited property. You can do this with Object#hasOwnProperty [MDN].

As alternative to for...in with hasOwnProperty, you can use Object.keys [MDN] to get an array of property names:

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

Arrays

To iterate over all elements of the data.items array, we use a for loop:

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

One could also use for...in to iterate over arrays, but there are reasons why this should be avoided: Why is 'for(var item in list)' with arrays considered bad practice in JavaScript?.

With the increasing browser support of ECMAScript 5, the array method forEach [MDN] becomes an interesting alternative as well:

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

In environments supporting ES2015 (ES6), you can also use the for...of [MDN] loop, which not only works for arrays, but for any iterable:

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

In each iteration, for...of directly gives us the next element of the iterable, there is no "index" to access or use.


What if the "depth" of the data structure is unknown to me?

In addition to unknown keys, the "depth" of the data structure (i.e. how many nested objects) it has, might be unknown as well. How to access deeply nested properties usually depends on the exact data structure.

But if the data structure contains repeating patterns, e.g. the representation of a binary tree, the solution typically includes to recursively [Wikipedia] access each level of the data structure.

Here is an example to get the first leaf node of a binary tree:

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

const root = {
    leftChild: {
        leftChild: {
            leftChild: null,
            rightChild: null,
            data: 42
        },
        rightChild: {
            leftChild: null,
            rightChild: null,
            data: 5
        }
    },
    rightChild: {
        leftChild: {
            leftChild: null,
            rightChild: null,
            data: 6
        },
        rightChild: {
            leftChild: null,
            rightChild: null,
            data: 7
        }
    }
};
function getLeaf(node) {
    if (node.leftChild) {
        return getLeaf(node.leftChild);
    } else if (node.rightChild) {
        return getLeaf(node.rightChild);
    } else { // node must be a leaf node
        return node;
    }
}

console.log(getLeaf(root).data);

A more generic way to access a nested data structure with unknown keys and depth is to test the type of the value and act accordingly.

Here is an example which adds all primitive values inside a nested data structure into an array (assuming it does not contain any functions). If we encounter an object (or array) we simply call toArray again on that value (recursive call).

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

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


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

console.log(toArray(data));



Helpers

Since the structure of a complex object or array is not necessarily obvious, we can inspect the value at each step to decide how to move further. console.log [MDN] and console.dir [MDN] help us doing this. For example (output of the Chrome console):

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

Here we see that that data.items is an array with two elements which are both objects. In Chrome console the objects can even be expanded and inspected immediately.

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

This tells us that data.items[1] is an object, and after expanding it we see that it has three properties, id, name and __proto__. The latter is an internal property used for the prototype chain of the object. The prototype chain and inheritance is out of scope for this answer, though.

忘你却要生生世世 2025-02-20 18:19:56

您可以以这种方式访问​​它

data.items[1].name

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

两种方式相等。

You can access it this way

data.items[1].name

or

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

Both ways are equal.

爱,才寂寞 2025-02-20 18:19:56

对象和数组具有许多内置方法,可以帮助您处理数据。

注意:在许多示例中,我正在使用。它们类似于函数表达式 用词法绑定。

object.keys.keys.keys.keys.keys() “ noreferrer”> object.values.values.values.values() < /a>(ES 2017)和“ noreferrer”> object.entries.entries.entries() < /a>(ES 2017)

object.keys()返回对象键的数组, object.values()返回对象值的数组, object.entries()返回对象键的数组和格式的相应值 [键,值]

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()带有循环和破坏分配

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

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

迭代 object.entries() a for loop 破坏分配

对于循环,您可以迭代数组元素。语法是 for的(数组的const元素)(我们可以用 const var 或或让,但它是最好使用 const ,如果我们不打算修改元素)。

破坏分配使您可以从数组或对象中提取值并将其分配给变量。在这种情况下该数组的以及 value 的第二个元素。它等同于此:

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

如您所见,破坏使它变得更加简单。

array.protototype.every.every()< /code> array.protototype.some.some()

every()方法返回 true 如果指定回调函数返回 true for 数组的每个元素。 一些()方法返回 true 如果指定的回调函数返回 true for 某些(至少一个)元素。

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

noreferrer“> array.protototype.find()< /code> array.protototype.filter()

find()方法返回第一个满足提供的回调功能的元素。 filter()方法返回满足提供的回调函数的所有 em> em 元素的数组。

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

noreferrer“> array.protototypotype.map()< /code>

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.protototype.dray型/code>

redaim()方法通过调用来将数组减少到单个值提供的回调功能具有两个元素。

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

redion()方法采用可选的第二个参数,这是初始值。当您调用 redion()的数组可以具有零或一个元素时,这很有用。例如,如果我们想创建一个函数 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

Objects and arrays has a lot of built-in methods that can help you with processing data.

Note: in many of the examples I'm using arrow functions. They are similar to function expressions, but they bind the this value lexically.

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

Object.keys() returns an array of object's keys, Object.values() returns an array of object's values, and Object.entries() returns an array of object's keys and corresponding values in a 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() with a for-of loop and destructuring assignment

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

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

It's very convenient to iterate the result of Object.entries() with a for-of loop and destructuring assignment.

For-of loop lets you iterate array elements. The syntax is for (const element of array) (we can replace const with var or let, but it's better to use const if we don't intend to modify element).

Destructuring assignment lets you extract values from an array or an object and assign them to variables. In this case const [key, value] means that instead of assigning the [key, value] array to element, we assign the first element of that array to key and the second element to value. It is equivalent to this:

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

As you can see, destructuring makes this a lot simpler.

Array.prototype.every() and Array.prototype.some()

The every() method returns true if the specified callback function returns true for every element of the array. The some() method returns true if the specified callback function returns true for some (at least one) element.

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

The find() methods returns the first element which satisfies the provided callback function. The filter() method returns an array of all elements which satisfies the provided callback function.

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() method returns an array with the results of calling a provided callback function on the array elements.

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() method reduces an array to a single value by calling the provided callback function with two elements.

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() method takes an optional second parameter, which is the initial value. This is useful when the array on which you call reduce() can has zero or one elements. For example, if we wanted to create a function sum() which takes an array as an argument and returns the sum of all elements, we could write it like that:

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

手心的海 2025-02-20 18:19:56

如果您试图从示例结构中访问 item id name ,而又不知道它在数组中的位置,则是最简单的这样做的方法是使用 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"}

根据我的经验,使用高阶功能而不是高阶功能或 for..in 循环产生的代码更易于推理,因此更可维护的代码。

只是我的2美分。

In case you're trying to access an item from the example structure by id or name, without knowing it's position in the array, the easiest way to do it would be to use underscore.js library:

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

From my experience, using higher order functions instead of for or for..in loops results in code that is easier to reason about, and hence more maintainable.

Just my 2 cents.

迷荒 2025-02-20 18:19:56

有时,需要使用字符串访问嵌套对象。例如,简单的方法是第一个级别,

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

但是复杂的JSON通常不是这种情况。随着JSON变得越来越复杂,找到JSON内部值的方法也变得复杂。浏览JSON的递归方法是最好的,并且如何利用递归的方法取决于所搜索的数据类型。如果涉及条件语句,则a json Search 可以是使用的好工具。

如果已知要访问的属性,但是路径很复杂,例如在此对象中

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

At times, accessing a nested object using a string can be desirable. The simple approach is the first level, for example

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

But this is often not the case with complex json. As json becomes more complex, the approaches for finding values inside of the json also become complex. A recursive approach for navigating the json is best, and how that recursion is leveraged will depend on the type of data being searched for. If there are conditional statements involved, a json search can be a good tool to use.

If the property being accessed is already known, but the path is complex, for example in this object

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

And you know you want to get the first result of the array in the object, perhaps you would like to use

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

However, that will cause an exception as there is no property of object with that name. The solution to be able to use this would be to flatten the tree aspect of the object. This can be done recursively.

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

Now, the complex object can be flattened

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

Here is a jsFiddle Demo of this approach being used.

薄情伤 2025-02-20 18:19:56

要访问嵌套属性,您需要指定其名称,然后浏览对象。

如果您已经知道确切的路径,那么您可以在脚本中像这样的脚本中进行硬码:

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

这些也可以使用 -

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

当您不知道之前不知道确切的名称,或者用户是为您提供名称的用户。然后需要动态搜索数据结构。这里有些人建议可以使用循环的进行搜索,但是有一种非常简单的方法可以使用 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)

路径是一种说明的方法:首先将对象带有键项目,这恰好是数组。然后取 1 -ST元素(0索引数组)。上一次在该数组元素中使用键 name 进行对象,恰好是字符串 bar

如果您的路径很长,您甚至可以使用 string.split 使所有这些更容易 -

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

这只是简单的JavaScript,而无需使用任何第三方库,例如jquery或lodash。

To access a nested attribute, you need to specify its name and then search through the object.

If you already know the exact path, then you can hardcode it in your script like so:

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

these also work -

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

When you don't know the exact name before hand, or a user is the one who provides the name for you. Then dynamically searching through the data structure is required. Some suggested here that the search can be done using a for loop, but there is a very simple way to traverse a path using 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)

The path is a way to say: First take the object with key items, which happens to be an array. Then take the 1-st element (0 index arrays). Last take the object with key name in that array element, which happens to be the string bar.

If you have a very long path, you might even use String.split to make all of this easier -

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

This is just plain JavaScript, without using any third party libraries like jQuery or lodash.

一指流沙 2025-02-20 18:19:56

以下是提到的4种不同的方法来获取JavaScript对象属性:

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

// Method 1
let method1 = data.items[1].name;
console.log(method1);

// Method 2
let method2 = data.items[1]["name"];
console.log(method2);

// Method 3
let method3 = data["items"][1]["name"];
console.log(method3);

// Method 4  Destructuring
let { items: [, { name: second_name }] } = data;
console.log(second_name);

Here are 4 different methods mentioned to get the javascript object property:

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

// Method 1
let method1 = data.items[1].name;
console.log(method1);

// Method 2
let method2 = data.items[1]["name"];
console.log(method2);

// Method 3
let method3 = data["items"][1]["name"];
console.log(method3);

// Method 4  Destructuring
let { items: [, { name: second_name }] } = data;
console.log(second_name);

新一帅帅 2025-02-20 18:19:56

这是简单的解释:

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

/*
1. `data` is object contain `items` object*/
console.log(data);

/*
2. `items` object contain array of two objects as elements*/
console.log(data.items);

/*
3. you need 2nd element of array - the `1` from `[0, 1]`*/
console.log(data.items[1]);

/*
4. and you need value of `name` property of 2nd object-element of array)*/
console.log(data.items[1].name);

It's simple explanation:

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

/*
1. `data` is object contain `items` object*/
console.log(data);

/*
2. `items` object contain array of two objects as elements*/
console.log(data.items);

/*
3. you need 2nd element of array - the `1` from `[0, 1]`*/
console.log(data.items[1]);

/*
4. and you need value of `name` property of 2nd object-element of array)*/
console.log(data.items[1].name);

终难愈 2025-02-20 18:19:56

您可以使用 lodash _get 函数:

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

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

You could use lodash _get function:

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

_.get(object, 'a[0].b.c');
// => 3
子栖 2025-02-20 18:19:56

这个问题很旧,因此作为当代更新。随着ES2015的发作,还有替代方案可以掌握所需的数据。现在有一个称为对象破坏的功能,用于访问嵌套对象。

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

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

console.log(secondName);

上面的示例从 name 键中创建一个称为 secondname 的变量跳过数组中的第一个对象。

值得注意的是,对于此示例而言,这可能是过分的,因为简单的数组易于阅读,但在分解对象时,它很有用。

这是对您特定用例的简短介绍,毁灭性可能是一种不寻常的语法。我建议阅读 Mozilla的破坏性分配文档更多的。

This question is quite old, so as a contemporary update. With the onset of ES2015 there are alternatives to get a hold of the data you require. There is now a feature called object destructuring for accessing nested objects.

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

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

console.log(secondName);

The above example creates a variable called secondName from the name key from an array called items, the lonely , says skip the first object in the array.

Notably it's probably overkill for this example, as simple array acccess is easier to read, but it comes in useful when breaking apart objects in general.

This is very brief intro to your specific use case, destructuring can be an unusual syntax to get used to at first. I'd recommend reading Mozilla's Destructuring Assignment documentation to learn more.

风铃鹿 2025-02-20 18:19:56
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://lealen.freecodecamp.org/javascript-algorithms-and-data-sinstructures/basic-javascript/accessing-nested-objects

rel = “ 因此:

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-algorithms-and-data-scruptures/basic-javascript/accessing-nested-arrays/

另一个更有用的文档,描述了上述情况:
https://developer.mozilla.org/en-us/docs/lealen/lealen/javascript/objects/basics#bracket_notation_notation

通过点步行属性访问: https://developer.mozilla.org/en-us/docs/web/javascript/reference/reference/property_accessors#dot_notation

var ourStorage = {


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

or

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

Basically, use a dot between each descendant that unfolds underneath it and when you have object names made out of two strings, you must use the ["obj Name"] notation. Otherwise, just a dot would suffice;

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

to add to this, accessing nested Arrays would happen like so:

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"

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

Another more useful document depicting the situation above:
https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Basics#Bracket_notation

Property access via dot walking: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Property_Accessors#Dot_notation

不奢求什么 2025-02-20 18:19:56

访问动态多级对象。

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/andreitodorut/3mws3kjl/

Accessing dynamically multi levels object.

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

Working fiddle: https://jsfiddle.net/andreitodorut/3mws3kjL/

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文