简体   繁体   中英

Recursively replace keys within an object of unknown size using Javascript

I would like to be able to replace certain keys within an object of dynamic size using Javascript. For example, I have an object that might look like this:

var obj = {
    where: {
        hypes: {
            lte: 12 <-- replace key
        },
        or: [
            {
                hypes: {
                    lt: 14 <-- replace key
                }
            },
            {
                id: {
                    lt: 10 <-- replace key
                }
            }
        ]
    } 
}

In order for this object to be used with Sequelize I need to convert the following keys to Sequelize operators: lt , or , and lte . I've created an operators object that acts as a dictionary so I can pull the Sequelize operator from it:

const operators = {
    'eq': [Op.eq],
    'lte': [Op.lte],
    'lt': [Op.lt],
    'or': [Op.or]
};

I was thinking I could use the operators object to match the key of the obj and replace it with the value of the operators object. I figured I could use the following recursive function to loop through the obj given its unknown size:

const iterate = (obj) => {
    Object.keys(obj).forEach(key => {

    console.log(`key: ${key}, value: ${obj[key]}`)

    if (typeof obj[key] === 'object') {
            iterate(obj[key])
        }
    })
}

The above function will check if the value of a key is an object and will call the iterate() method again.

Thus I can call: iterate(obj) and it'll recursively map through all nested properties in the object.

The issue I am having is how do I replace the keys when they match a property inside the operators object so that I'll end up with an obj that looks like this:

var obj = {
    where: {
        hypes: {
            lte: 12
        },
        [Op.or]: [ <-- changed
            {
                hypes: {
                    [Op.lt]: 14 <-- changed
                }
            },
            {
                id: {
                    [Op.lt]: 10 <-- changed
                }
            }
        ]
    } 
}

Thanks!

You could take a recursive approach.

 function replace(object) { return Array.isArray(object) ? object.map(replace) : object && typeof object === 'object' ? Object.fromEntries(Object .entries(object) .map(([k, v]) => [k in operators ? operators[k] : k, replace(v)]) ) : object; } var obj = { where: { hypes: { lte: 12 }, or: [{ hypes: { lt: 'xx' } }, { id: { lt: 10 } }] } }; const operators = { eq: '[Op.eq]', lte: '[Op.lte]', lt: '[Op.lt]', or: '[Op.or]' }; console.log(replace(obj));

In your recursive function when you hit the leaf, you can change the key and delete the older one.

 var obj = { where: { hypes: { lte: 12 }, or: [{ hypes: { lt: 14 } }, { id: { lt: 10 } } ] } }; const operators = { eq: '[Op.eq]', lte: '[Op.lte]', lt: '[Op.lt]', or: '[Op.or]' }; const iterate = (obj) => { Object.keys(obj).forEach(key => { // console.log(`key: ${key}, value: ${obj[key]}`) if (typeof obj[key] === 'object') { iterate(obj[key]) } if (operators[key]) { obj[operators[key]] = obj[key]; delete obj[key]; } }); }; iterate(obj) console.log(obj)

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