Преобразовать объект нотации с меткой javascript в вложенный объект
Я пытаюсь создать функцию, которая расширяет объект, например:
{
'ab.cd.e' : 'foo',
'ab.cd.f' : 'bar',
'ab.g' : 'foo2'
}
Вложенный объект:
{ab: {cd: {e:'foo', f:'bar'}, g:'foo2'}}
Подобно этой php-функции: Set:: expand()
Без использования eval, конечно.
Ответы
Ответ 1
Я считаю, что это то, что вам нужно:
function deepen(o) {
var oo = {}, t, parts, part;
for (var k in o) {
t = oo;
parts = k.split('.');
var key = parts.pop();
while (parts.length) {
part = parts.shift();
t = t[part] = t[part] || {};
}
t[key] = o[k]
}
return oo;
}
Например:
> JSON.stringify(deepen({'ab.cd.e' : 'foo', 'ab.cd.f' : 'bar', 'ab.g' : 'foo2'}))`
"{"ab":{"cd":{"e":"foo","f":"bar"},"g":"foo2"}}"
Ответ 2
Если вы используете Node.js(например, если не вырезать и вырезать из нашего модуля), попробуйте этот пакет: https://www.npmjs.org/package/dataobject-parser
Построен модуль, который выполняет операции прямого/обратного вызова:
https://github.com/Gigzolo/dataobject-parser
Он создан как объект, управляемый самостоятельно. Используется для экземпляра экземпляра DataObjectParser.
var structured = DataObjectParser.transpose({
'ab.cd.e' : 'foo',
'ab.cd.f' : 'bar',
'ab.g' : 'foo2'
});
structured.data()
возвращает ваш вложенный объект:
{ab: {cd: {e:'foo', f:'bar'}, g:'foo2'}}
Итак, вот рабочий пример в JSFiddle:
http://jsfiddle.net/H8Cqx/
Ответ 3
Название функции ужасно, и код был быстро создан, но он должен работать. Обратите внимание, что это изменяет исходный объект, я не уверен, хотите ли вы создать новый объект, который является расширенной версией старого.
(function(){
function parseDotNotation( str, val, obj ){
var currentObj = obj,
keys = str.split("."), i, l = keys.length - 1, key;
for( i = 0; i < l; ++i ) {
key = keys[i];
currentObj[key] = currentObj[key] || {};
currentObj = currentObj[key];
}
currentObj[keys[i]] = val;
delete obj[str];
}
Object.expand = function( obj ) {
for( var key in obj ) {
parseDotNotation( key, obj[key], obj );
}
return obj;
};
})();
var expanded = Object.expand({
'ab.cd.e' : 'foo',
'ab.cd.f' : 'bar',
'ab.g' : 'foo2'
});
JSON.stringify( expanded );
//"{"ab":{"cd":{"e":"foo","f":"bar"},"g":"foo2"}}"
Ответ 4
Получено из ответ Esailija с исправлениями для поддержки нескольких ключей верхнего уровня.
(function () {
function parseDotNotation(str, val, obj) {
var currentObj = obj,
keys = str.split("."),
i, l = Math.max(1, keys.length - 1),
key;
for (i = 0; i < l; ++i) {
key = keys[i];
currentObj[key] = currentObj[key] || {};
currentObj = currentObj[key];
}
currentObj[keys[i]] = val;
delete obj[str];
}
Object.expand = function (obj) {
for (var key in obj) {
if (key.indexOf(".") !== -1)
{
parseDotNotation(key, obj[key], obj);
}
}
return obj;
};
})();
var obj = {
"pizza": "that",
"this.other": "that",
"alphabets": [1, 2, 3, 4],
"this.thing.that": "this"
}
Выходы:
{
"pizza": "that",
"alphabets": [
1,
2,
3,
4
],
"this": {
"other": "that",
"thing": {
"that": "this"
}
}
}
Ответ 5
Вам нужно преобразовать каждый строковый ключ в объект. Используя следующую функцию, вы можете получить желаемый результат.
function convertIntoJSON(obj) {
var o = {}, j, d;
for (var m in obj) {
d = m.split(".");
var startOfObj = o;
for (j = 0; j < d.length ; j += 1) {
if (j == d.length - 1) {
startOfObj[d[j]] = obj[m];
}
else {
startOfObj[d[j]] = startOfObj[d[j]] || {};
startOfObj = startOfObj[d[j]];
}
}
}
return o;
}
Теперь вызовите эту функцию
var aa = {
'ab.cd.e': 'foo',
'ab.cd.f': 'bar',
'ab.g': 'foo2'
};
var desiredObj = convertIntoJSON(aa);
Ответ 6
Что-то, что работает, но, вероятно, не самый эффективный способ сделать это (также полагается на метод ECMA 5 Object.keys(), но его можно легко заменить.
var input = {
'ab.cd.e': 'foo',
'ab.cd.f': 'bar',
'ab.g': 'foo2'
};
function createObjects(parent, chainArray, value) {
if (chainArray.length == 1) {
parent[chainArray[0]] = value;
return parent;
}
else {
parent[chainArray[0]] = parent[chainArray[0]] || {};
return createObjects(parent[chainArray[0]], chainArray.slice(1, chainArray.length), value);
}
}
var keys = Object.keys(input);
var result = {};
for(var i = 0, l = keys.length; i < l; i++)
{
createObjects(result, keys[i].split('.'), input[keys[i]]);
}
JSFiddle - здесь.
Ответ 7
Вы можете разделить строку ключа как путь и уменьшить ее для присвоения значения, используя объект по умолчанию для непосещенных уровней.
function setValue(object, path, value) {
var keys = path.split('.'),
last = keys.pop();
keys.reduce((o, k) => o[k] = o[k] || {}, object)[last] = value;
return object;
}
var source = { 'ab.cd.e': 'foo', 'ab.cd.f': 'bar', 'ab.g': 'foo2' },
target = Object
.entries(source)
.reduce((o, [k, v]) => setValue(o, k, v), {});
console.log(target);