recorrer objetos objeto dinamicas crear array alternativa javascript json nested eval

dinamicas - Acceder o crear objetos JavaScript anidados con la clave de cadena sin eval



recorrer array de objetos javascript (2)

Estoy buscando una buena solución para acceder a una propiedad por valor de cadena, pero si la propiedad no existe, debería crearla. Si la estructura raíz ya ha definido algunas partes de la estructura, los atributos no se deben sobrescribir, sino que deben fusionarse.

Por ejemplo, si tiene una test objeto vacía y desea establecer una estructura profunda sin usar eval. p.ej

test = {} test.foo.name = "Hallo" // <<- foo is an Object test.foo[3] = "Test" // <<- foo should remain as Object, not as Array test.foo.data[3].bar = 100 // <<- should not overwrite test.foo.name

He escrito una solución que realmente funciona, pero es un código bastante malo, supongo:

También disponible como jsfiddle: https://jsfiddle.net/gvaLzqqf/4/

Object.setValue = function(node, flatKey, value) { flatKey = flatKey.replace("[", "."); flatKey = flatKey.replace("]", ""); var parts = flatKey.split(".") var oldNode = node parts.forEach(function(key, index) { if (/^/+?(0|[1-9]/d*)$/.test(key)) { key = key * 1 if (index > 0) { var oldValue = parts[index - 1] if (!Array.isArray(oldNode[oldValue])) { oldNode[oldValue] = [] node = oldNode[oldValue] } } } if (node[key] == undefined) { node[key] = {} } oldNode = node node = node[key] }); // for each oldNode[parts[parts.length - 1]] = value return oldNode[parts[parts.length - 1]] } // function var test = {} Object.setValue(test, "foo.name", "Mr. Foo") Object.setValue(test, "foo.data[0].bar", 100) Object.setValue(test, "and.another[2].deep", 20) console.log("test = " + JSON.stringify(test)) console.log("test.foo.data[0].bar = " + test.foo.data[0].bar)

Sin embargo, ¿hay alguna forma mejor de lograr esto?


No reinventaría la rueda en este caso, y en cambio usaría lodash . Específicamente la función set () . Según su ejemplo:

var object = { ''a'': [{ ''b'': { ''c'': 3 } }] }; _.set(object, ''a[0].b.c'', 4); console.log(object.a[0].b.c); // => 4 _.set(object, [''x'', ''0'', ''y'', ''z''], 5); console.log(object.x[0].y.z); // => 5


Podrías dividir el camino y reducir el camino caminando el objeto dado. Si no existe ningún objeto, cree una nueva propiedad con el nombre o una matriz. Más tarde asigne el valor.

function setValue(object, path, value) { var way = path.replace(//[/g, ''.'').replace(//]/g, '''').split(''.''), last = way.pop(); way.reduce(function (o, k, i, kk) { return o[k] = o[k] || (isFinite(i + 1 in kk ? kk[i + 1] : last) ? [] : {}); }, object)[last] = value; } var test = {}; setValue(test, "foo.name", "Mr. Foo"); setValue(test, "foo.data[0].bar", 100); setValue(test, "and.another[2].deep", 20); console.log(test);