2012-02-27 18 views
15

Let decir que tengo datos JSON comoCómo acceder a anidada datos JSON

data = {"id":1, 
     "name":"abc", 
     "address": {"streetName":"cde", 
        "streetId":2 
        } 
     } 

Ahora que estoy recibiendo campos que se accede desde estos datos JSON como: fields = ["id", "name", "address.streetName"]

¿Cómo podría acceder tercer campo (address.streetName) a partir de datos JSON dados de la manera más eficiente? data.fields[2] no funciona

Una posibilidad es construyo data[address][streetName] cadena usando un bucle y hacer eval de eso, pero ¿hay alguna manera eficiente de hacerlo?

+0

¿Qué pasa con data.address.streetName? – Dampsquid

+0

Obtengo address.streetName como una variable de alguna parte. Quiero decir que alguien me está pasando x donde x = "address.streetName" – user999491

+0

Hmm, en ese caso, tendrías que usar 'eval', ¡que no es exactamente ideal! Para usar eval: 'var su_variable = eval (" datos. "+ X);' – JamieJag

Respuesta

29

Para ser sincero, no puedo entender su problema. JSON ya está estructurado, ¿por qué necesita cambiar la estructura?

En le caso, me gustaría acceder a ella de la siguiente manera:

data.address.streetName; 

Si, por casualidad, lo que quiere es travesía los datos, se necesitaría:

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

Actualización

Después de leer a continuación, lo que este usuario necesita parece más obvio. Dados los nombres de propiedad como una cadena, él/ella quiere acceder al objeto.

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

+1 Creo que tienes 'data.address.streetName' correcto, eso es lo que está buscando, aunque su pregunta no está clara. – Sarfraz

+0

Hmm Lo explicaré de nuevo: address.streetName es una variable que viene a mí. Tengo datos en formato json conmigo. La situación es como si tuviera datos en formato JSON y alguien me está pasando "address.streetName" y el problema es cómo debo acceder al valor de esta clave a partir de los datos – user999491

+0

@ user999491. Ver mi respuesta actualizada. – Christian

2

Su variable data no tiene una propiedad fields, y es por eso que data.fields[2] no funciona. Creo que lo que estás tratando de hacer es data[fields[2]], que funcionaría para un objeto simple, pero no puedes indexar en un objeto complejo como ese.

+0

sí correcto, ¿hay alguna manera eficiente de acceder a los datos anidados en comparación con los siguientes: col = "address.streetName" // key exp = "x" // datos; col = col.split (".") for (var i = 0; i user999491

2

puede acceder a él de esta manera data.address.streetName

+0

Sí, pero estoy obteniendo la clave en formato de cadena ... Quiero decir que alguien me está pasando "address.streetName" – user999491

+0

@ user999491 Podrías haber dicho eso en primer lugar ... – Christian

+0

no puedes simplemente recorrer tu registros y hacer un 'si address.streetname == x' –

1

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

Salida:

id=1 
name=abc 
address.streetName=cde 
+0

Gracias Michael ... esto es lo que estoy haciendo ... simplemente me pregunto si podría haber una manera más eficiente de hacer eso ... – user999491

+0

Me acabo de dar cuenta de que estaba haciendo una evaluación innecesaria después de la construcción data ["address"] ["streetName"] usando for loop. Creo que la respuesta de usted es más eficiente. Muchas gracias. – user999491

6

Para resumir, se puede utilizar la notación de matriz object[property] en lugar de object.property; Esto es especialmente útil cuando las teclas contiene caracteres especiales:

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 

Usted puede utilizar el operador typeof para comprobar si existe o no una propiedad o no antes de usarlo:

typeof data["address"]["streetName"]; // returns "string" 
typeof data["address"]["foobarblah"]; // returns "undefined" 
12

Si utiliza lodash (una muy popular biblioteca de utilidades), puede usar _.get().

p. Ej.

var data = { 
    "id":1, 
    "name": "abc", 
    "address": { 
    "streetName": "cde", 
    "streetId":2 
    } 
} 
_.get(data, 'address.streetName'); 
// 'cde' 
_.get(data, ['address', 'streetName']); 
// 'cde' 

Si se trata de una matriz, puede utilizar la ruta cadena como 'address[0].streetName' también.

p. Ej.

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 

Internamente, se utiliza toPath() función para convertir camino cadena (por ejemplo address.streetName) en una matriz (por ejemplo ['address', 'streetName']), y luego utiliza una función para acceder a los datos en la trayectoria dada dentro del objeto.

Otras funciones de utilidad similares incluyen _.set() y _.has(). Échales un vistazo.

+0

lodash es bastante sencillo de hacer esto. –

Cuestiones relacionadas