簡體   English   中英

將 javascript 點符號 object 轉換為嵌套 object

[英]Convert javascript dot notation object to nested object

我正在嘗試構建一個 function 來擴展 object,例如:

{
    'ab.cd.e' : 'foo',
    'ab.cd.f' : 'bar',
    'ab.g' : 'foo2'
}

進入嵌套 object:

{ab: {cd: {e:'foo', f:'bar'}, g:'foo2'}}

像這樣 php function: Set::expand()

當然不使用 eval 。

我相信這就是你所追求的:

 function deepen(obj) { const result = {}; // For each object path (property key) in the object for (const objectPath in obj) { // Split path into component parts const parts = objectPath.split('.'); // Create sub-objects along path as needed let target = result; while (parts.length > 1) { const part = parts.shift(); target = target[part] = target[part] || {}; } // Set value at end of path target[parts[0]] = obj[objectPath] } return result; } // For example ... console.log(deepen({ 'ab.cd.e': 'foo', 'ab.cd.f': 'bar', 'ab.g': 'foo2' }));

如果您使用的是 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/

函數名稱很糟糕,代碼很快就完成了,但它應該可以工作。 請注意,這會修改原始對象,我不確定您是否要創建一個舊對象的擴展版本的新對象。

(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"}}"

源自Esailja 的答案,修復了支持多個頂級鍵的問題。

(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"
        }
    }
}

小提琴

您可以將鍵字符串拆分為路徑,並通過使用未訪問級別的默認對象來減少它以分配值。

 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);

這是@broofa 提供的答案,但已轉換為 TypeScript。

type NestedObject = { [key: string]: any };

function objectify(obj: NestedObject): NestedObject {
  const result: NestedObject = {};
  for (const key in obj) {
    let target: NestedObject = result;
    const parts = key.split(".");
    for (let j = 0; j < parts.length - 1; j++) {
      const part = parts[j];
      target = target[part] = target[part] || {};
    }
    target[parts[parts.length - 1]] = obj[key];
  }
  return result;
}

這是我在我的一個應用程序中執行此操作的方法:

 const obj = { "start.headline": "1 headline", "start.subHeadline": "subHeadline", "start.accordion.headline": "2 headline", "start.accordion.sections.0.content": "content 0", "start.accordion.sections.0.iconName": "icon 0", "start.accordion.sections.1.headline": "headline 1", "start.accordion.sections.1.content": "content 1", "start.accordion.sections.1.iconName": "icon 1", "start.accordion.sections.2.headline": "headline 2", "start.accordion.sections.2.content": "content 2", "start.accordion.sections.2.iconName": "icon 2", "end.field": "add headline", "end.button": "add button", "end.msgs.success": "success msg", "end.msgs.error": "error msg", }; const res = Object.keys(obj).reduce((res, key) => { const path = key.split('.'); const lastIndex = path.length - 1; path.reduce( (acc, k, i, a) => acc[k] = lastIndex === i? obj[key]: acc[k] || (/\d/.test(a[i+1])? []: {}), res ); return res; }, {}); console.log(res);

您需要將每個字符串鍵轉換為對象。 使用以下功能,您可以獲得所需的結果。

 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);

可行的方法,但可能不是最有效的方法(也依賴於 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 在這里

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM