简体   繁体   English

通过KeyName查找JSON数组对象值

[英]Finding JSON Array Object Values by KeyName

I am looking for a HashMap sort of implementation in Javascript for JSON for the following case. 我正在针对以下情况在JSON中寻找一种HashMap的实现形式。

I have the JSON with following structure: 我有以下结构的JSON:

{
"level1": {
    "level2": [{
        "product1": [
            "item1",
            "item2"
        ]
    }, {
        "product2": [
            "item1",
            "item2"
        ]
    }, {
        "product3": [
            "item5",
            "item6"
        ]
    }]
}
}

For my use case, I get a value , say 'product3', I want to find values for this key ie "item5", "item6". 对于我的用例,我得到一个值,例如“ product3”,我想找到该键的值,即“ item5”,“ item6”。 I have a way, that i can loop through the entire level2 object but want to know if I can simply use key to find values. 我有一种方法,可以遍历整个level2对象,但想知道是否可以简单地使用key来查找值。

You can build yourself either an object or (in ES2015) a Map : 您可以自己构建一个对象或(在ES2015中)构建Map

Here's an ES5 example using an object: 这是一个使用对象的ES5示例:

var map = Object.create(null);
data.level1.level2.forEach(function(entry) {
    Object.keys(entry).forEach(function(key) {
        map[key] = entry;
    });
});

Live example: 现场示例:

 var data = { "level1": { "level2": [{ "product1": [ "item1", "item2" ] }, { "product2": [ "item1", "item2" ] }, { "product3": [ "item5", "item6" ] }] } }; var map = Object.create(null); data.level1.level2.forEach(function(entry) { Object.keys(entry).forEach(function(key) { map[key] = entry; }); }); var name = "product2"; console.log(map[name]); 

We create the object ( map ) using Object.create(null) so that it doesn't have a prototype, and so doesn't have the pre-existing inherited properties like toString and valueOf . 我们使用Object.create(null)创建对象( map ),以便它没有原型,因此也没有像toStringvalueOf这样的预先存在的继承属性。

The inner loop, on the result of Object.keys , is necessary because each object in the level2 array has a different name for its only property. 必须使用Object.keys结果上的内部循环,因为level2数组中的每个对象为其唯一属性都具有不同的名称。 That's an unusual and a bit awkward structure. 这是一个不寻常且有点尴尬的结构。

In ES2015 (aka "ES6") with Map , it's very similar you just use new Map and set : 在带有Map ES2015(又称“ ES6”)中,非常相似,只是使用new Mapset

var map = new Map();
data.level1.level2.forEach(function(entry) {
    Object.keys(entry).forEach(function(key) {
        map.set(key, entry);
    });
});

Live example: 现场示例:

 var data = { "level1": { "level2": [{ "product1": [ "item1", "item2" ] }, { "product2": [ "item1", "item2" ] }, { "product3": [ "item5", "item6" ] }] } }; var map = new Map(); data.level1.level2.forEach(function(entry) { Object.keys(entry).forEach(function(key) { map.set(key, entry); }); }); var name = "product2"; console.log(map.get(name)); 

"One-line" optimized solution using Array.some , Array.indexOf and Object.keys functions (no need to iterate through all "product" objects): 使用Array.someArray.indexOfObject.keys函数的“单行”优化解决方案(无需遍历所有“产品”对象):

// json is your initial object
var key = 'product3', values;
json['level1']['level2'].some((v) => Object.keys(v).indexOf(key) !== -1 && (values = v[key]), values);

console.log(values);  // ["item5", "item6"]

Explanation : 说明
arr.some(callback[, thisArg]) - This function returns true if the callback function returns a truthy value for any array element; arr.some(callback[, thisArg]) -如果回调函数返回任何数组元素的真实值,则此函数返回true;否则,此函数返回true In my example values becomes thisArg parameter which should contain values of the desired "keyName". 在我的示例中, values变成thisArg参数,其中应包含所需的“ keyName”的值。
It will iterate through all "product" objects, but will stop looping immediately if the required keyName is found amoung the properties of the current object ( Object.keys(v).indexOf(key) !== -1 ). 它将迭代所有“产品”对象,但是如果在当前对象的属性( Object.keys(v).indexOf(key) !== -1 )中找到所需的keyName ,它将立即立即停止循环。
As a concurrent condition it should save the values of found object which can be achieved with truthy assignment expression && (values = v[key]) . 作为并发条件,它应保存找到的对象的值,这可以通过真实的赋值表达式&& (values = v[key])
That's all. 就这样。

You could just transform data to different structure. 您可以将数据转换为不同的结构。

 const data = { "level1": { "level2": [{ "product1": [ "item1", "item2" ] }, { "product2": [ "item3", "item4" ] }, { "product3": [ "item5", "item6" ] }] }, "level1b": { "level2": [{ "product1": [ "item1b", "item2" ] }, { "product2": [ "item3", "item4" ] }, { "product3": [ "item5", "item6" ] }] } }; const transformed = Object .keys(data) .reduce((obj, key) => { const value = data[key]; return Object.assign(obj, {[key]: transformLvl2(value)}); }, {}); console.log(transformed.level1.level2.product2); console.log(transformed.level1.level2.product1); console.log(transformed.level1.level2.product3); console.log(transformed.level1b.level2.product1); function transformLvl2(level2) { return Object .keys(level2) .reduce((obj, key) => { const value = level2[key]; return Object.assign(obj, {[key]: transformLvl3(value)}); }, {}); } function transformLvl3(level3) { return level3 .reduce((obj, value) => { return Object.assign(obj, value); }, {}); } 

try (assuming that level1 and level2 is generic) 试试(假设level1level2是通用的)

 var obj = { "level1": { "level2": [{ "product1": [ "item1", "item2" ] }, { "product2": [ "item1", "item2" ] }, { "product3": [ "item5", "item6" ] }] } }; var keyName = "product3"; var items = []; Object.keys(obj).forEach(function(key) { Object.keys( obj[key] ).forEach(function(key1){ obj[key][key1].forEach(function(obj1){ Object.keys(obj1).forEach(function(key2) { if (key2 == keyName) { items = items.concat(obj1[key2]); } }); }); }); }); console.log(items); 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM