Как получить доступ к вложенным данным 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"