Как получить доступ к вложенным данным JSON
Скажем, у меня есть данные json, такие как
data = {"id":1,
"name":"abc",
"address": {"streetName":"cde",
"streetId":2
}
}
Теперь я получаю поля для доступа к данным json, например: fields = ["id", "name", "address.streetName"]
Как я могу получить доступ к третьему полю (address.streetName
) из данных json наиболее эффективным способом?
data.fields[2]
не работает
Одна из возможностей заключается в том, что я строю строку data[address][streetName]
, используя цикл for и делаю eval из этого, но есть ли эффективный способ сделать это?
Ответы
Ответ 1
Честно говоря, я не могу понять вашу проблему. JSON уже структурирован, почему вам нужно изменить структуру?
В этом случае я бы получил доступ к нему следующим образом:
data.address.streetName;
Если, во всяком случае, вы хотите, чтобы пересечь данные, вам понадобится:
function traverse_it(obj){
for(var prop in obj){
if(typeof obj[prop]=='object'){
// object
traverse_it(obj[prop[i]]);
}else{
// something else
alert('The value of '+prop+' is '+obj[prop]+'.');
}
}
}
traverse_it(data);
Обновление
После прочтения ниже, что этот пользователь нуждается, кажется более очевидным. Учитывая имена свойств в виде строки, он/она хочет получить доступ к объекту.
function findProp(obj, prop, defval){
if (typeof defval == 'undefined') defval = null;
prop = prop.split('.');
for (var i = 0; i < prop.length; i++) {
if(typeof obj[prop[i]] == 'undefined')
return defval;
obj = obj[prop[i]];
}
return obj;
}
var data = {"id":1,"name":"abc","address":{"streetName":"cde","streetId":2}};
var props = 'address.streetName';
alert('The value of ' + props + ' is ' + findProp(data, props));
Ответ 2
Если вы используете lodash (очень популярную библиотеку утилиты), вы можете использовать _.get()
.
например.
var data = {
"id":1,
"name": "abc",
"address": {
"streetName": "cde",
"streetId":2
}
}
_.get(data, 'address.streetName');
// 'cde'
_.get(data, ['address', 'streetName']);
// 'cde'
Если он содержит массив, вы можете использовать также путь строки, например 'address[0].streetName'
.
например.
var data = {
"id":1,
"name": "abc",
"addresses": [
{
"streetName": "cde",
"streetId": 2
},
{
"streetName": "xyz",
"streetId": 102
},
]
}
_.get(data, 'addresses[0].streetName');
// cde
_.get(data, [address, 1, streetName]);
// xyz
Внутри он использует функцию toPath()
для преобразования строкового пути (например, address.streetName
) в массив (например, ['address', 'streetName']
), а затем использует функцию для доступа к данным по заданному пути внутри объекта.
Другие подобные функции полезности включают _.set()
и _.has()
. Проверьте их.
Ответ 3
Короче говоря, вы можете использовать нотацию массива object[property]
вместо object.property
; это особенно полезно, когда ключи содержат специальные символы:
var data = {
"id": 1,
"name": "abc",
"address": {
"streetName": "cde",
"streetId": 2
}
}
data.address.streetName; // (1) dot notation
data["address"]["streetName"]; // (2) array notation
var field = "streetName";
data["address"][field]; // (3) variable inside array notation
var fields = "address.streetName".split(".");
data[fields[0]][fields[1]]; // (4) specific to your question
Вы можете использовать оператор typeof
для проверки наличия или отсутствия свойства перед его использованием:
typeof data["address"]["streetName"]; // returns "string"
typeof data["address"]["foobarblah"]; // returns "undefined"
Ответ 4
Ваша переменная data
не имеет свойства fields
, и поэтому data.fields[2]
не работает. Я думаю, что вы пытаетесь сделать там data[fields[2]]
, который будет работать для простого объекта, но вы не можете индексировать такой сложный объект.
Ответ 5
вы можете получить к нему доступ таким образом data.address.streetName
Ответ 6
JavaScript:
function getProperty(json, path) {
var tokens = path.split(".");
var obj = json;
for (var i = 0; i < tokens.length; i++) {
obj = obj[tokens[i]];
}
return obj;
}
var data = {
id: 1,
name: "abc",
address: {
streetName: "cde",
streetId: 2
}
};
var fields = ["id", "name", "address.streetName"];
for (var i = 0; i < fields.length; i++) {
var value = getProperty(data, fields[i]);
console.log(fields[i] + "=" + value);
}
Вывод:
id=1
name=abc
address.streetName=cde
Ответ 7
Это функция, которую я использую для поиска данных во вложенных объектах:
Object.prototype.find = function() {
try {
return Array.prototype.slice.call(arguments).reduce(function(acc, key) {
return acc[key]
}, this)
}
catch(e) {
return
}
}
Структура данных:
data = {
"id":1,
"name":"abc",
"address": {
"streetName":"cde",
"streetId":2
}
}
Вызов функции:
data.find("address","streetName")
Возвращает:
"cde"