从Array创建未知深度的Object的通用解决方案

时间:2017-12-06 21:32:02

标签: javascript

我需要创建一个JSON对象,如下所示:

{
    "app_name": "foo",
    "meta": {
        "title": "foo",
        "lang": "bar"
    },
    "teaser": {
        "foo": {
            "headline": "foo",
            "subline": "bar"
        }
    }
}

对象树按以下表示形式提供:

var translations = [
    {
        "key": "app_name",
        "val": "foo"
    },
    {
        "key": "meta.title",
        "val": "foo"
    },
    {
        "key": "meta.lang",
        "val": "bar"
    },
    {
        "key": "teaser.foo.headline",
        "val": "foo"
    },
    {
        "key": "teaser.foo.subline",
        "val": "bar"
    }
];

现在,我无法找到通用的解决方案。这里有一些适用于给定(简化)示例的代码:

var finalObject = {};
for (var i in translations) {
    var translation = translations[i],
        translationKey = translation["key"],
        translationVal = translation["val"]; 

    var keyArray = translationKey.split("."),
        keyDepth = keyArray.length;

    if (keyDepth === 1) {
        finalObject[keyArray[0]] = translationVal;
    } else if (keyDepth === 2) {
        if (typeof finalObject[keyArray[0]] === 'object') { 
            finalObject[keyArray[0]][keyArray[1]] = translationVal;
        } else {
            var item = {};
            item[keyArray[1]] = translationVal;
            finalObject[keyArray[0]] = item;
        }
    } else if (keyDepth === 3) {
        if (finalObject[keyArray[0]] && finalObject[keyArray[0]][keyArray[1]] && typeof finalObject[keyArray[0]][keyArray[1]] === 'object') { 
            finalObject[keyArray[0]][keyArray[1]][keyArray[2]] = translationVal;
        } else {
            var item = {};
            item[keyArray[2]] = translationVal;
            if (!finalObject[keyArray[0]] || typeof finalObject[keyArray[0]] !== 'object') {
                finalObject[keyArray[0]] = {};
            }
            finalObject[keyArray[0]][keyArray[1]] = item;
        }
    }
}

但这是不可靠的丑陋。我想替换这部分:

    if (keyDepth === 1) {
        finalObject[keyArray[0]] = translationVal;
    } else if (keyDepth === 2) {
       //...
    }

    if (keyDepth === 1) {
        finalObject[keyArray[0]] = translationVal;
    } else {
        //some generic solution, which works for any deepth
    }

有什么想法吗?

1 个答案:

答案 0 :(得分:4)

如果属性不存在,您可以使用默认对象采用迭代方法。

function setValue(object, key, value) {
    var path = key.split('.'),
        last = path.pop();

    path.reduce(function (o, k) {
        return o[k] = o[k] || {};
    }, object)[last] = value;
}

var translations = [{ key: "app_name", val: "foo" }, { key: "meta.title", val: "foo" }, { key: "meta.lang", val: "bar" }, { key: "teaser.foo.headline", val: "foo" }, { key: "teaser.foo.subline", val: "bar" }],
    object = {};

translations.forEach(function (o) {
    setValue(object, o.key, o.val);
});

console.log(object);
.as-console-wrapper { max-height: 100% !important; top: 0; }