How to convert a nested javascript object to only first level properties object? - Stack Overflow

admin2025-04-19  0

I have the below object inputObj and I want to convert it to a simple object like outputObj.

var inputObj = {
    'a' : 1,
    'b' : true,
    'c' : 'string1',
    'd' : {
        'e' : 'string2',
        'f' : false,
        'g' : 5,
        'h' : {
            'i' : 7,
            'j' : 'string3',
            'k' : [
                {
                    'name' : 'l',
                    'value': 11
                },
                {
                    'name' : 'm',
                    'value': {
                        'n' : 13,
                        'o' : 'string4'
                    }
                }
            ]
        }
    },
    'p' : [
        {
            'name' : 'q',
            'value': 15
        },
        {
            'name' : 'r',
            'value': 'Awesome!'
        }
    ]
}

var outputObj = {
    'a' : 1,
    'b' : true,
    'c' : 'string1',
    'e' : 'string2',
    'f' : false,
    'g' : 5,
    'i' : 7,
    'j' : 'string3',
    'l' : 11,
    'n' : 13,
    'o' : 'string4',
    'q' : 15,
    'r' : 'Awesome!'
}

Please note that in case of array the final output object would be build from name and value properties as per above example.

I have tried to implement the same using below code. I know as I am calling the nested function, the final object is getting reset and the scope is also different there. May be basic closure concept can solve this but I am confused with this. If you can correct my code or altogether new code is also fine.

function convertToFirstLevelObject( object ) {
	var returnObj = {};

	if( IsPrimaryDataType( object )) {
		return object;
	}
	else {
		if( object instanceof Array ) {
	        for ( var i = 0; i < object.length; i++ ) {
	        	if( typeof object[i] === 'object' && !(object[i] instanceof Array) ) {
	        		var key   = object[i]['name'],
	        			value = object[i]['value'];
	        		if( IsPrimaryDataType( value )) {
	        			returnObj[ key ] = value;
	        		}
	        		else {
	        			convertToFirstLevelObject( value );
	        		}
	        	}
	        	else{
	        		/* This condition is for Array of Array */
	        		if( object[i] instanceof Array ) {
	        			convertToFirstLevelObject( object[i] );
	        		} else {
	        			console.log('Wrong data passed, expected data id object or Array of objects');
	        			return;
	        		}
	        	}
	        }
		}
		else {
			for ( var attr in object ) {
	            if ( object.hasOwnProperty( attr ) ) {
	            	if( IsPrimaryDataType( object[ attr ] )) {
	            		returnObj[ attr ] = object[ attr ];
	            	}
	            	else {
	            		convertToFirstLevelObject( object[ attr ] )
	            	}
	            } 
	        }
		}
	}
	return returnObj;
}

function IsPrimaryDataType( input ) {
	var returnFlag = false;
	if( input === null || input === 'undefined' || typeof input !==  'object' ) {
		returnFlag = true;
	}
	return returnFlag;
}

I have the below object inputObj and I want to convert it to a simple object like outputObj.

var inputObj = {
    'a' : 1,
    'b' : true,
    'c' : 'string1',
    'd' : {
        'e' : 'string2',
        'f' : false,
        'g' : 5,
        'h' : {
            'i' : 7,
            'j' : 'string3',
            'k' : [
                {
                    'name' : 'l',
                    'value': 11
                },
                {
                    'name' : 'm',
                    'value': {
                        'n' : 13,
                        'o' : 'string4'
                    }
                }
            ]
        }
    },
    'p' : [
        {
            'name' : 'q',
            'value': 15
        },
        {
            'name' : 'r',
            'value': 'Awesome!'
        }
    ]
}

var outputObj = {
    'a' : 1,
    'b' : true,
    'c' : 'string1',
    'e' : 'string2',
    'f' : false,
    'g' : 5,
    'i' : 7,
    'j' : 'string3',
    'l' : 11,
    'n' : 13,
    'o' : 'string4',
    'q' : 15,
    'r' : 'Awesome!'
}

Please note that in case of array the final output object would be build from name and value properties as per above example.

I have tried to implement the same using below code. I know as I am calling the nested function, the final object is getting reset and the scope is also different there. May be basic closure concept can solve this but I am confused with this. If you can correct my code or altogether new code is also fine.

function convertToFirstLevelObject( object ) {
	var returnObj = {};

	if( IsPrimaryDataType( object )) {
		return object;
	}
	else {
		if( object instanceof Array ) {
	        for ( var i = 0; i < object.length; i++ ) {
	        	if( typeof object[i] === 'object' && !(object[i] instanceof Array) ) {
	        		var key   = object[i]['name'],
	        			value = object[i]['value'];
	        		if( IsPrimaryDataType( value )) {
	        			returnObj[ key ] = value;
	        		}
	        		else {
	        			convertToFirstLevelObject( value );
	        		}
	        	}
	        	else{
	        		/* This condition is for Array of Array */
	        		if( object[i] instanceof Array ) {
	        			convertToFirstLevelObject( object[i] );
	        		} else {
	        			console.log('Wrong data passed, expected data id object or Array of objects');
	        			return;
	        		}
	        	}
	        }
		}
		else {
			for ( var attr in object ) {
	            if ( object.hasOwnProperty( attr ) ) {
	            	if( IsPrimaryDataType( object[ attr ] )) {
	            		returnObj[ attr ] = object[ attr ];
	            	}
	            	else {
	            		convertToFirstLevelObject( object[ attr ] )
	            	}
	            } 
	        }
		}
	}
	return returnObj;
}

function IsPrimaryDataType( input ) {
	var returnFlag = false;
	if( input === null || input === 'undefined' || typeof input !==  'object' ) {
		returnFlag = true;
	}
	return returnFlag;
}

Edit: Here is another inputObj just to show that nesting can be of any level, here I have increased the level of array nesting. In any level of array nesting it will just look for if there is any object which has name and value both the property then it will flatten that.

 var inputObj = {
    'a' : 1,
    'b' : true,
    'c' : 'string1',
    'd' : {
        'e' : 'string2',
        'f' : false,
        'g' : 5,
        'h' : {
            'i' : 7,
            'j' : 'string3',
            'k' : [
                {
                    'name' : 'l',
                    'value': 11
                },
                {
                    'name' : 'm',
                    'value': [{'n' : 13},{'o' : 'string4'}]
                }
            ]
        }
    },
    'p' : [
        {
            'name' : 'q',
            'value': 15
        },
        {
            'name' : 'r',
            'value': 'Awesome!'
        }
    ],
    's' : [
        [{
            'name' : 't',
            'value': 17
        },
        {
            'name' : 'u',
            'value': 'string5'
        }],
        [ 1, 2, 3],
        [ "string6", "string7", "string8"],
        [
            [1,3,5],
            [{'name' : 'v', 'value' : 19, 'anyOtherProp' : false}],
            [2,4,6],
            [{'name' : 'w', 'otherProp' : 31}]
        ]
    ]
}

OutObj should be like below

var outputObj = {
    'a' : 1,
    'b' : true,
    'c' : 'string1',
    'e' : 'string2',
    'f' : false,
    'g' : 5,
    'i' : 7,
    'j' : 'string3',
    'l' : 11,
    'n' : 13,
    'o' : 'string4',
    'q' : 15,
    'r' : 'Awesome!',
    't' : 17,
    'u' : 'string5',
    'v' : 19
}
Share edited Sep 10, 2016 at 15:49 Debajit Majumder asked Sep 9, 2016 at 11:48 Debajit MajumderDebajit Majumder 9342 gold badges12 silver badges23 bronze badges 6
  • gist.github./penguinboy/762197 – Rayon Commented Sep 9, 2016 at 11:50
  • @Rayon flattening JS objects is a pletely different question – Bergi Commented Sep 9, 2016 at 11:51
  • @Bergi – But input appears object, not JSON – Rayon Commented Sep 9, 2016 at 11:53
  • I don't see outputObj. Anyway, in what way does your code fail? Have you tried walking through the code in the debugger? – user663031 Commented Sep 9, 2016 at 12:08
  • @Rayon - Your solution may help me to solve my problem. But currently it will not yield the exact output object which I want. – Debajit Majumder Commented Sep 9, 2016 at 18:24
 |  Show 1 more ment

2 Answers 2

Reset to default 4

You could use an iterative and recursive approach for looping the object.

function flatObject(source, target) {
    Object.keys(source).forEach(k => {
        if (Array.isArray(source[k])) {
            source[k].forEach(function iter(a) {
                if (Array.isArray(a)) {
                    a.forEach(iter);
                    return;
                }
                if (a !== null && typeof a === 'object') {
                    if ('name' in a || 'value' in a) {
                        'name' in a && 'value' in a && flatObject({ [a.name]: a.value }, target);
                        return;
                    }
                    flatObject(a, target);
                }
            });
            return;
        }
        if (source[k] !== null && typeof source[k] === 'object') {
            flatObject(source[k], target);
            return;
        }
        target[k] = source[k];
    });
}

var inputObj = { 'a': 1, 'b': true, 'c': 'string1', 'd': { 'e': 'string2', 'f': false, 'g': 5, 'h': { 'i': 7, 'j': 'string3', 'k': [{ 'name': 'l', 'value': 11 }, { 'name': 'm', 'value': [{ 'n': 13 }, { 'o': 'string4' }] }] } }, 'p': [{ 'name': 'q', 'value': 15 }, { 'name': 'r', 'value': 'Awesome!' }], 's': [[{ 'name': 't', 'value': 17 }, { 'name': 'u', 'value': 'string5' }], [1, 2, 3], ["string6", "string7", "string8"], [[1, 3, 5], [{ 'name': 'v', 'value': 19, 'anyOtherProp': false }], [2, 4, 6], [{ 'name': 'w', 'otherProp': 31 }]]] },
    target = {};

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

Another approach. Very clear in my opinion. It relies heavily on recursion.

function convert(obj, mem) {
    if (typeof obj != 'object' || obj === null) { // return primitive values and null directly
        return obj
    }
    else if (obj.hasOwnProperty("name")) { // convert {name,value} objects to regular ones and recurse
        if (!obj.value) return // value is required - if not available bail out
        var o = {}
        o[obj.name] = obj.value
        return convert(o, mem)
    }
    else if (Array.isArray(obj)) { // iterate over array items and recurse
        obj.forEach(function (item) {
            convert(item, mem)
        })
    }
    else {
        for (var key in obj) { // iterate object items
            var value = obj[key]
            if (typeof value === "object") { // convert nested objects, dispose key
                convert(value, mem)
            }
            else {
                mem[key] = value // keep everything else
            }
        }
    }
    return mem // return result
}
转载请注明原文地址:http://conceptsofalgorithm.com/Algorithm/1745072821a283388.html

最新回复(0)