0

I have an object literal like below.

{
  is_active: true,
  start_date: { [Symbol(lt)]: 2020-02-24T12:56:36.780Z },
  expiry_date: { [Symbol(gt)]: 2020-02-24T12:56:36.780Z },
  [Symbol(or)]: [ { user_id: 'M' }, { user_id: null } ]
}

These objects are automatically generated by sequelize before querying to database

I need to iterate through all object keys and change the value of that key which is id or ends with _id.
This is my first time with Symbol datatype. I read a article here, It says they can't be iterate using for...in or object...keys
I also read an answer here, but It only said how to access it.
Below is my function that iterate recursively though the object and decrypts id and value of keys ending with _id

   function decryptIds(obj) {
          if (typeof obj === 'object' && obj !== null) {
            for (let key in obj) {
              if (Array.isArray(obj[key])) {
                for(let i = 0; i< obj[key].length; i++) {
                  if(typeof obj[key][i] === 'object' && obj[key][i] !==null)
                    decryptIds(obj[key][i].where)
                  else 
                    obj[key][i] = decrypt(obj[key][i])
                }
              } else if (typeof obj[key] === 'object' && obj !== null) {
                decryptIds(obj[key].where)
              }
              else if (key === 'id' || key.endsWith('_id')) {
                obj[key] = decrypt(obj[key])
              }
            }
          }
          return
        }
        decryptIds(model.where)
sujeet
  • 3,480
  • 3
  • 28
  • 60
  • why not use s/t iterable like `AND`, `OR`, etc as key? – Nina Scholz Feb 24 '20 at 13:20
  • @NinaScholz Sorry, I didn't put much information, I will update though. Those objects are auto generated by sequelize itself before querying to db. So I can't change them. – sujeet Feb 24 '20 at 13:22
  • One of the purposes of symbols is to explicitly disallow this usecase--if you're constructing the query do the modification before you get the symbolized result. – Dave Newton Feb 24 '20 at 13:45

1 Answers1

0

Somehow, I managed to do it. I know it's not the solution, it's easily feasible. I will keep try until I get any better approach. For now it is okay.

      beforeFind: (model, options) => {
        function decryptIds(obj) {
          if(typeof obj === 'object' && obj!==snull &&Object.getOwnPropertySymbols(obj)) {
            const objectSymbols = obj[Object.getOwnPropertySymbols(obj)[0]]
            if(objectSymbols) {
              objectSymbols.forEach(el => {
                decryptIds(el)
              })
            }
          }
          if (typeof obj === 'object' && obj !== null) {
            for (let key in obj) {
              if (Array.isArray(obj[key])) {
                for(let i = 0; i< obj[key].length; i++) {
                  if(typeof obj[key][i] === 'object' && obj[key][i] !==null)
                    decryptIds(obj[key][i].where)
                  else 
                    obj[key][i] = decrypt(obj[key][i])
                }
              }
              else if (key === 'id' || key.endsWith('_id')) {
                if(obj[key]) {
                  obj[key] = decrypt(obj[key])
                }
              } else if (typeof obj[key] === 'object' && obj !== null) {
              decryptIds(obj[key].where)
            }
            }
          }
          return
        }
        console.log(model.where)
        decryptIds(model.where)
        console.log(model.where)
      },
sujeet
  • 3,480
  • 3
  • 28
  • 60