Convert javascript dot notation object to nested object

后端 未结 7 1203
我在风中等你
我在风中等你 2020-11-28 09:54

I\'m trying to build a function that would expand an object like :

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


        
相关标签:
7条回答
  • 2020-11-28 10:27

    You need to convert each string key into object. Using following function you can get desire result.

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

    Now call this function

     var aa = {
                    'ab.cd.e': 'foo',
                    'ab.cd.f': 'bar',
                        'ab.g': 'foo2'
                    };
       var desiredObj =  convertIntoJSON(aa);
    
    0 讨论(0)
  • 2020-11-28 10:32

    I believe this is what you're after:

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

    0 讨论(0)
  • 2020-11-28 10:32

    Something that works, but is probably not the most efficient way to do so (also relies on ECMA 5 Object.keys() method, but that can be easily replaced.

    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 is here.

    0 讨论(0)
  • 2020-11-28 10:33

    You could split the key string as path and reduce it for assigning the value by using a default object for unvisited levels.

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

    0 讨论(0)
  • 2020-11-28 10:40

    Derived from Esailija's answer, with fixes to support multiple top-level keys.

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

    Outputs:

    {
        "pizza": "that",
        "alphabets": [
            1,
            2,
            3,
            4
        ],
        "this": {
            "other": "that",
            "thing": {
                "that": "this"
            }
        }
    }
    

    Fiddle

    0 讨论(0)
  • 2020-11-28 10:46

    If you're using Node.js (e.g. - if not cut and paste out of our module), try this package: https://www.npmjs.org/package/dataobject-parser

    Built a module that does the forward/reverse operations:

    https://github.com/Gigzolo/dataobject-parser

    It's designed as a self managed object right now. Used by instantiating an instance of DataObjectParser.

    var structured = DataObjectParser.transpose({
        'ab.cd.e' : 'foo',
        'ab.cd.f' : 'bar',
        'ab.g' : 'foo2'
    });                                                                                                                                                                                                                                                                                                                                                                                                                                                   
    

    structured.data() returns your nested object:

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

    So here's a working example in JSFiddle:

    http://jsfiddle.net/H8Cqx/

    0 讨论(0)
提交回复
热议问题