简体   繁体   中英

How to recursively list object properties and list them all in a 'one-level-deep'-object?

I want to do the following: from a JS object, I want to build a second one, listing recursively all properties from the first, but all at 'level one' and whose name is the 'path' inside the first object.

Here is an example. The following object...

{
    level1_simple: 'foo',
    level1_object: {
        level2_a: 'bar',
        level2_b: 'bar2'
    },
    level1_array: [
        {
            property1: 'foobar',
            property2: 'foobar2'
        },
        'element2'
    ]
}

Should be translated as:

{
    level1_simple: 'foo',

    level1_object[level2_a]: 'bar',
    level1_object[level2_b]: 'bar2',

    level1_array[0][property1]: 'foobar',
    level1_array[0][property2]: 'foobar2',
    level1_array[1]: 'element2'
}

I've written a recursive function that would work well except for the two following issues I can't manage to solve:

  1. Strings are parsed as arrays of characters instead of strings
  2. I do not know how to detect the 'leaf' properties (termination condition) , since each property always seems to have a '0' property, which itself has a '0' property, etc.

Here is the full code (that results in an endless loop due to point 2 above):

function _treatDataRecursive( data, newData, prefix )
{
    console.log( 'Entering: ' + prefix +"\n" );

    // Iterate over the properties of data
    for( property in data )
    {
        console.log( 'Listing properties: ' + property + " value = " + data[property] + "\n" );
        // Build property symfonyzed name (using recursion)
        var newPropName = prefix + '[' + property + ']';
        // Check if property is a leaf
        var type = typeof property;
        if( type === 'string' || type === 'number' || type === 'boolean' )
        {
            console.log( 'Property is a leaf: ' + property +"\n" );
            // Property is a leaf: add property/value to newData
            newData[newPropName] = data[property];
        } else {
            // Recursive call to go one level deeper
            _treatDataRecursive( property, newData, newPropName );
        }
    }
}

You have only one big problem. You should be using the actual value of the property , not the property itself.

function _treatDataRecursive(data, newData, prefix) {
    for (var property in data) {
        // if prefix is empty, don't decorate the property
        var newPropName = prefix ? prefix + '[' + property + ']' : property;
        // get the type of the actual value, not the `property`
        var type = typeof data[property];

        // If it is an object and not null do the recursion
        if (type === 'object' && data[property] !== null) {
            _treatDataRecursive(data[property], newData, newPropName);
        } else {
            // Most likely a leaf, don't recurse now
            newData[newPropName] = data[property];
        }
    }
}

var obj = {};
_treatDataRecursive(data, obj, "");
console.log(obj);

Output

{ level1_simple: 'foo',
  'level1_object[level2_a]': 'bar',
  'level1_object[level2_b]': 'bar2',
  'level1_array[0][property1]': 'foobar',
  'level1_array[0][property2]': 'foobar2',
  'level1_array[1]': 'element2' }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM