Parsing Webhook Json Object using Function Node

Hi,

I have a web-hook which receives data from external source, in that web-hook i would like to pick up a specific key/value pairs out… Please refere the example below.

[
{
"headers": {
"x-real-ip": “XX”.XX.XX.XX,
"x-forwarded-for": “XX.XX.XX.XX,
"host": "proud-dodo-12.hooks.n8n.cloud",
"x-forwarded-proto": "https",
"x-nginx-proxy": "true",
"connection": "close",
"content-length": "4184",
"content-type": "application/json",
"user-agent": "PostmanRuntime/7.29.0",
"accept": "*/*",
"postman-token": "74c74411-f9ab-4597-b479-ad826aeff379",
"accept-encoding": "gzip, deflate, br"
},
"params": {
},
"query": {
},
"body": [
{
"body": {
"token": "7fgtWdVkVZdglnioJwnnoGD5",
"team_id": "T032648LE",
"api_app_id": "A02BXC7MW3U",
"event": {
"bot_id": "B02C3J9NCSG",
"type": "message",
"text": " XXXXX”,
"user": "U02BUBQ4C2H",
"ts": "1655387376.165869",
"app_id": "A02BXC7MW3U",
"team": "T032648LE",
"bot_profile": {
"id": "B02C3J9NCSG",
"deleted": false,
"name": "NOC_Ticket_Automator",
"updated": 1629525536,
"app_id": "A02BXC7MW3U",
"icons": {
"image_36": "https://a.slack-edge.com/80588/img/plugins/app/bot_36.png",
"image_48": "https://a.slack-edge.com/80588/img/plugins/app/bot_48.png",
"image_72": "https://a.slack-edge.com/80588/img/plugins/app/service_72.png"
},
"team_id": "T032648LE"
},
"attachments": [
{
"id": 1,
"color": "ff0000",
"fallback": “test data`"
}
],
"blocks": [
{
"type": "rich_text",
"block_id": "=UZIm",
"elements": [
{
"type": "rich_text_section",
"elements": [...] // 7 items
}
]
}
],
"channel": "C010B2SSYP3",
"event_ts": "1655387376.165869",
"channel_type": "group"
},
"type": "event_callback",
"event_id": "Ev03LND3Q1U0",
"event_time": 1655387376,
"authorizations": [
{
"enterprise_id": null,
"team_id": "T032648LE",
"user_id": "U02BUBQ4C2H",
"is_bot": true,
"is_enterprise_install": false
}
],
"is_ext_shared_channel": false,
"event_context": "4-eyJldCI6Im1lc3NhZ2UiLCJ0aWQiOiJUMDMyNjQ4TEUiLCJhaWQiOiJBMDJCWEM3TVczVSIsImNpZCI6IkMwMTBCMlNTWVAzIn0"
}
}
]
}
]

In the above example, i am interested in getting the value for “user” key(“user”: “U02BUBQ4C2H”). I know that we can use a SET node to achieve it, however the payload is not the same all the time, meaning, sometimes the “user” Key will be inside the “body”,“event” block and some time it will be inside the “message” block and sometimes the key will be in “attachment” block kind of nested and we are not sure as to where these key/value will be placed.

What i am trying to achieve is, irrespective of where that key/value present in the payload, i would like to write a javascript function, node which can iterate through the entire payload and find my key/value alone.

The “user” key is unique on the payload, so there are no duplicates. Please refer me to some samples with similar requirement where i can write the code.

You could use a Function Item node and the Spread Operator to combine the properties.

item.payload = [
    ...item.body.event,
    ...item.body.message,
]

You would need to know all the possible locations it could be.

Then use the Set node and item.payload.user.

Alternatively, while flexible but inelegant, you could JSON.stringify the whole item and use regex to search the text:

var user = (JSON.stringify(item.body)).match(/"user":"([a-zA-Z0-9]+)"/)[1];

Good luck

Hi @ctrl-freak ,

I tried the JSON.Stringify method, how ever i am getting the below error message.

Stack
TypeError: executionData.every is not a function
    at Object.normalizeItems (/usr/local/lib/node_modules/n8n/node_modules/n8n-core/dist/src/NodeExecuteFunctions.js:772:23)
    at Object.execute (/usr/local/lib/node_modules/n8n/node_modules/n8n-nodes-base/dist/nodes/Function/Function.node.js:97:34)
    at processTicksAndRejections (internal/process/task_queues.js:95:5)
    at async Workflow.runNode (/usr/local/lib/node_modules/n8n/node_modules/n8n-workflow/dist/src/Workflow.js:594:28)
    at async /usr/local/lib/node_modules/n8n/node_modules/n8n-core/dist/src/WorkflowExecute.js:537:49

Here is my function node code.

const data = $node["Webhook"].json;
var user = (JSON.stringify(data.body)).match(/"user":"([a-zA-Z0-9]+)"/)[1];
return { user }

Please help.

Can you provide a clean dump of the full JSON? The one above is a bit mangled due to smart quotes. Avoid pasting into Word, as it’ll do all sorts of funky things.

Hi,

I am sorry i cant share the entire JSON since there are lot of sensitive data and its not possible for me to verify every line to remove those… Any other way we can achieve the same ?

Hi,

I suspect the Spread Operator isn’t liking that some of the properties aren’t arrays; the regex matching may be more reliable.

You should be able to use a Function Item node with the input data, and not have to reference the Webhook node. From there, you should be able to JSON.stringify(item.body).:

The dummy data node contains the JSON you provided above, fixed as much as I could. The ‘Match User’ contains the code useful for you.

Try that and let me know how you go.

Thanks will check and get back to you