2010-12-13 21 views
8

Tengo un objeto Javascript anidado comoJavascript: los valores acceso anidados en los datos JSON utilizando nombres de variables dinámicas

var data = { 'name': { 'heading': 'Name', 'required': 1, 'type': 'String' }, 
      'profile': { 
        'age': { 'heading': 'Age', 'required': 0, 'type': 'Number' }, 
        'phone': { 'heading': 'Phone', 'required': 0, 'type': 'String'}, 
        'city': { 'heading': 'City', 'required': 0, 'type': 'String'}, 
        }, 
      'status': { 'heading': 'Status', 'required': 1, 'type': 'String' } 
      }; 

Aquí, pueden acceder a los campos como data.profile.age.type o data.name.type . Sin problemas Y si tengo nombres de variables dinámicos, puedo acceder de la siguiente manera. De nuevo, sin problemas.

f = 'profile'; data[f].age.type 

Pero, aquí tengo los nombres de variables como el 'nombre', 'profile.age', etc 'profile.city' y, obviamente, no puedo acceder a ellos como f 'profile.age'; data [f] .type que no funcionará.

¿Alguien me puede guiar cómo acceder a ellos (obtener/configurar) de la manera más directa y sencilla?

Nota: Intenté esto y funciona para get.

data.get = function(p) { o = this; return eval('o.'+p); }; 
f = 'profile.age'; data.get(f).name; 

Aunque el conjunto no parece ser lo suficientemente simple. Por favor, avíseme si hay mejores soluciones para get y set también.

+2

Tenías razón para hacer esta pregunta en el SO. Cada vez que te encuentres utilizando eval en Javascript, seguramente estás haciendo lo incorrecto. –

+0

Gracias por informarme acerca de eval. ¡Puede ser eval es malo! :-) – rsmoorthy

+0

Lo dijiste. Eche un vistazo a la última sugerencia ofrecida aquí: http://javascript.crockford.com/code.html –

Respuesta

7

No utilice eval menos que sea absolutamente necesario. :) Por lo menos en este caso, hay mejores maneras de hacerlo - se puede dividir el nombre anidado en partes individuales e iterar sobre ellos:

data.get = function(p) { 
    var obj = this; 

    p = p.split('.'); 
    for (var i = 0, len = p.length; i < len - 1; i++) 
    obj = obj[p[i]]; 

    return obj[p[len - 1]]; 
}; 

data.set = function(p, value) { 
    var obj = this; 

    p = p.split('.'); 
    for (var i = 0, len = p.length; i < len - 1; i++) 
    obj = obj[p[i]]; 

    obj[p[len - 1]] = value; 
}; 
+0

Gracias. Respuesta muy rápida y útil. – rsmoorthy

8

Usted sólo puede anidar los corchetes:

var a = 'name', b = 'heading'; 
data[a][b]; // = `Name` 
+1

esto no responde la pregunta en absoluto ... – vsync

+1

@vsync: Claro que sí. Lo digo en lugar de 'var a = 'name.heading'; datos [a] ', puede usar conjuntos sucesivos de corchetes para acceder a niveles más profundos del objeto. Entonces, si sabe que está buscando algo en el objeto 'profile',' var a = 'profile', b = 'age'; data [a] [b] 'funciona. Obviamente, si necesita manejar una cadena arbitraria, las otras respuestas muestran cómo hacerlo. Esta es una alternativa si alguien no necesita la complejidad de analizar cadenas arbitrarias '" a.b.c.d "'. – josh3736

2

Tal vez una función que toma en el camino hacia la propiedad que le interesa y lo divide en fichas que representan propiedades. Algo como esto (esto es muy difícil, por supuesto):

data.get = function(path) { 
    var tokens = path.split('.'), val = this[tokens[0]]; 
    if (tokens.length < 2) return val; 
    for(var i = 1; i < tokens.length; i++) { 
    val = val[tokens[i]]; 
    } 
    return val; 
} 

ejemplo:

var f = 'one.two'; 
    var data = { one: {two:'hello'}}; 
    data.get = /* same as above */; 

    var val = data.get(f); 
0

Este utiliza la función jquery.each() para recorrer hacia abajo un árbol json usando una variable de cadena que puede contener o no uno o más ".". Alternativamente, puede pasar una matriz y omitir .split();

pathString = algo así como "person.name"

jsonObj = {algo así como "persona": { "name": "Valerie"}}.

function getGrandchild(jsonObj, pathString){ 
    var pathArray = pathString.split("."); 
    var grandchild = jsonObj; 
    $.each(pathArray, function(i, item){ 
     grandchild = grandchild[item]; 
    }); 
    return grandchild; 
}; 

devuelve "Valerie"

Cuestiones relacionadas