How to unflatten a JavaScript object in a daisy-chain/dot notation into an object with nested objects and arrays?

后端 未结 3 1915
梦毁少年i
梦毁少年i 2021-01-05 06:37

I want to unflatten an object like this...

var obj2 = {
    \"firstName\": \"John\",
    \"lastName\": \"Green\",
    \"car.make\": \"Honda\",
    \"car.mode         


        
3条回答
  •  耶瑟儿~
    2021-01-05 07:07

    You could walk the splitted substrings and a temporary object with a check if the key exists and build a new property with a check for the next property if it is a finite number, then assign an array, otherwise an object. At last assign with the last substring the value to the temp object.

    function unflatten(obj) {
        var result = {}, temp, substrings, property, i;
        for (property in obj) {
            substrings = property.split('.');
            temp = result;
            for (i = 0; i < substrings.length - 1; i++) {
                if (!(substrings[i] in temp)) {
                    if (isFinite(substrings[i + 1])) { // check if the next key is
                        temp[substrings[i]] = [];      // an index of an array
                    } else {
                        temp[substrings[i]] = {};      // or a key of an object
                    }
                }
                temp = temp[substrings[i]];
            }
            temp[substrings[substrings.length - 1]] = obj[property];
        }
        return result;
    };
    
    var obj2 = { "firstName": "John", "lastName": "Green", "car.make": "Honda", "car.model": "Civic", "car.revisions.0.miles": 10150, "car.revisions.0.code": "REV01", "car.revisions.0.changes": "", "car.revisions.1.miles": 20021, "car.revisions.1.code": "REV02", "car.revisions.1.changes.0.type": "asthetic", "car.revisions.1.changes.0.desc": "Left tire cap", "car.revisions.1.changes.1.type": "mechanic", "car.revisions.1.changes.1.desc": "Engine pressure regulator", "visits.0.date": "2015-01-01", "visits.0.dealer": "DEAL-001", "visits.1.date": "2015-03-01", "visits.1.dealer": "DEAL-002" };
    
    console.log(unflatten(obj2));
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    A slightly more compact version could be this

    function unflatten(object) {
        var result = {};
        Object.keys(object).forEach(function (k) {
            setValue(result, k, object[k]);
        });
        return result;
    }
    
    function setValue(object, path, value) {
        var way = path.split('.'),
            last = way.pop();
    
        way.reduce(function (o, k, i, kk) {
            return o[k] = o[k] || (isFinite(i + 1 in kk ? kk[i + 1] : last) ? [] : {});
        }, object)[last] = value;
    }
    
    var obj2 = { "firstName": "John", "lastName": "Green", "car.make": "Honda", "car.model": "Civic", "car.revisions.0.miles": 10150, "car.revisions.0.code": "REV01", "car.revisions.0.changes": "", "car.revisions.1.miles": 20021, "car.revisions.1.code": "REV02", "car.revisions.1.changes.0.type": "asthetic", "car.revisions.1.changes.0.desc": "Left tire cap", "car.revisions.1.changes.1.type": "mechanic", "car.revisions.1.changes.1.desc": "Engine pressure regulator", "visits.0.date": "2015-01-01", "visits.0.dealer": "DEAL-001", "visits.1.date": "2015-03-01", "visits.1.dealer": "DEAL-002" };
    
    console.log(unflatten(obj2));
    .as-console-wrapper { max-height: 100% !important; top: 0; }

提交回复
热议问题