Я написал утилиту, я думаю, что вы найдете полезными для этого: https://github.com/forms-js/forms-js/blob/master/source/utils/flatten.ts
Вот соответствующие биты. Это написано в TypeScript, но если вы удалите аннотации типа:, это действительный JavaScript.
/**
* Writes a value to the location specified by a flattened key and creates nested structure along the way as needed.
*
* <p>For example, writing "baz" to the key 'foo.bar' would result in an object <code>{foo: {bar: "baz"}}</code>.
* Writing 3 to the key 'foo[0].bar' would result in an object <code>{foo: [{bar: 3}]}</code>.
*/
function write(value:any, flattenedKey:string, object:any):void {
var currentKey:any;
var keyIndexStart = 0;
for (var charIndex = 0, length = flattenedKey.length; charIndex < length; charIndex++) {
var character = flattenedKey.charAt(charIndex);
switch(character) {
case '[':
currentKey = flattenedKey.substring(keyIndexStart, charIndex);
createPropertyIfMissing_(currentKey, object, Array);
break;
case ']':
currentKey = flattenedKey.substring(keyIndexStart, charIndex);
currentKey = parseInt(currentKey); // Convert index from string to int
// Special case where we're targeting this object in the array
if (charIndex === length - 1) {
object[currentKey] = value;
} else {
// If this is the first time we're accessing this Array key we may need to initialize it.
if (!object[currentKey] && charIndex < length - 1) {
switch(flattenedKey.charAt(charIndex + 1)) {
case '[':
object[currentKey] = [];
break;
case '.':
object[currentKey] = {};
break;
}
}
object = object[currentKey];
}
break;
case '.':
currentKey = flattenedKey.substring(keyIndexStart, charIndex);
// Don't do anything with empty keys that follow Array indices (e.g. anArray[0].aProp)
if (currentKey) {
createPropertyIfMissing_(currentKey, object, Object);
}
break;
default:
continue; // Continue to iterate...
break;
}
keyIndexStart = charIndex + 1;
if (currentKey) {
object = object[currentKey];
}
}
if (keyIndexStart < flattenedKey.length) {
currentKey = flattenedKey.substring(keyIndexStart, flattenedKey.length);
object[currentKey] = value;
}
}
/**
* Helper method for initializing a missing property.
*
* @throws Error if unrecognized property specified
* @throws Error if property already exists of an incorrect type
*/
function createPropertyIfMissing_(key:string, object:any, propertyType:any):void {
switch(propertyType) {
case Array:
if (!object.hasOwnProperty(key)) {
object[key] = [];
} else if (!(object[key] instanceof Array)) {
throw Error('Property already exists but is not an Array');
}
break;
case Object:
if (!object.hasOwnProperty(key)) {
object[key] = {};
} else if (typeof object[key] !== 'object') {
throw Error('Property already exists but is not an Object');
}
break;
default:
throw Error('Unsupported property type');
break;
}
}
Чтобы быть справедливым, вы могли бы также рассмотреть проект написанный конкретно для этого - а не мой, в которой это лишь небольшая часть - что сказать, https://github.com/hughsk/flat
Очень хорошее решение. Сложный, но +1 для записи значения последнему ключу в объекте. Я специально не задавал этот вопрос в своем вопросе, но я считаю это хорошим вариантом в моем проекте. – undefinedman