Filtering nested JSON in JavaScript transformer

If an API request for users returns data in the following JSON format:

[
  {
    "ID": "1234",
    "Name": "Jane Doe",
    "Permissions": [
      {
        "Item": "abcd",
        "Allow": true
      },
      {
        "Item": "efgh",
        "Allow": false
      }
    ],
    "Profile": "wxyz"
  },
{
    "ID": "5678",
    "Name": "John Smith",
    "Permissions": [
      {
        "Item": "ijkl",
        "Allow": true
      }
    ],
    "Profile": "wxyz"
  }
]

while a different API request for Permissions returns data in the following JSON format:

[
  {
    "ID": "abcd",
    "Name": "Level 1",
  },
  {
    "ID": "efgh",
    "Name": "Level 2",
  },
  {
    "ID": "ijkl",
    "Name": "Level 3",
  }
]

How would I be able to use the JavaScript transformer to return a object with a user's ID, Name, and Permission names?
(eg. 1234 | Jane Doe | Level 1, Level 2)

I don't seem to be able to read properties of the nested JSON using indexing, such that I cannot find the object where the Permission.ID equals the User.Permissions.Index.Item.

I've tried the following to even get the first item of a user's permissions, but am told message:"Cannot read properties of undefined (reading 'Item')"

const users = {{getUsers.data}}
const permissions = {{getPermissions.data}}

let final_data = [];
Object.keys(users).forEach(key=> {  
  let new_obj = {}
  new_obj['id'] = users[key]['ID']
  new_obj['name'] = users[key]['Name'] 
  new_obj['permission'] = permissions.find(obj => obj.ID === users[key]['Permissions']['0']['Item'])
  final_data.push(new_obj)
})
return final_data;

Your help would be much appreciated!
Thomas

If the data that is being returned from your resource contains a column of JSON data -- its possible that data is still just a string. You may have to convert that string to an object:

const permissions = JSON.parse(getPermissions.data)

Thanks for the response, but I don't think that's it. {{ getUsers.data }} as far as I can tell is already an Object, so trying to JSON.parse it would just throw an [object Object] is not valid JSON error.

The issue seems to be in accessing keys within a user's Permissions property. It's probably the way I was trying to filter out if the property was null before attempting to get each of the names (not shown in above code).

Ahh ok, so its more about the code you are trying to write. I think you can do something like this:

users.map( user => {
   // current users permissions mapped
   const mappedPermissions = user.permissions.reduce( (result, permission) => {
      const namedPerms = perms.filter( perm => perm.ID === permission.Item && perm.Allow )
      if( namedPerms.length ) {
       result.push({ 
         ...permission,
         name: namedPerms[0].Name
       })
       return result
   }, [])
   return {
      ...user,
      permissions: mappedPermissions 
    }
}}
  1. We map (loop) over the user
  2. Then we reduce (loop with a map) over that users permissions
  3. For each of those permissions we find the corresponding Perm (using filter)
  4. If we got a perm and that perm was allowed we copy the name into the current users permissions

This is obviously not tested -- but this should give you a head start

2 Likes

Thanks. That got me sufficiently started.

Strangely, what I was doing before worked in JavaScript a different tool I was using.

1 Like

@ThomasLu_EarthDaily glad that helped!