如何将一个嵌套的javascript对象转换为只有一级属性对象

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

本文关键字:对象 转换 属性 一级 一个 嵌套 javascript      更新时间:2023-09-26

我有下面的对象inputObj,我想把它转换成一个简单的对象,如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!'
}

请注意,在array的情况下,最终输出对象将根据上述示例从namevalue属性构建。

我试图实现相同的使用下面的代码。我知道当我调用嵌套函数时,最终对象被重置,作用域也不同。可能基本的闭包概念可以解决这个问题,但我对此感到困惑。如果你能纠正我的代码或完全新的代码也很好。

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

编辑:

这里是另一个inputObj,只是为了表明嵌套可以是任何级别的,这里我增加了数组嵌套的级别。在任何级别的数组嵌套中,它都会查找是否存在同时具有namevalue属性的对象然后将其平化。

 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应该像

下面那样
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
}

您可以使用迭代和递归的方法来循环对象。

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

另一种方法。在我看来很清楚。它严重依赖于递归。

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
}