JSON Parser Multiple Arrays

shellypoeckes
Tera Contributor

Hello everyone,

 

I will give a thumbs up to anybody who can help me here.

 

I'm trying to parse information (highlighted fields in yellow attachment payload) from an Okta json suspend event payload that has a multiple arrays and then calling a sub flow to suspend the user in ServiceNow.

Please see payload attachment.

 

Here's scripted REST API.  It works if I put [0] where yellow highlighted but when I use [loop] it does not.  This payload can contain multiple suspends and that's why I cannot use [0].

 

shellypoeckes_0-1706208506057.png

 

 

 

2 ACCEPTED SOLUTIONS

There is an error in your code: the for loop variable needs to be checked against parsed.data.events.length not parsed.data.length.

As for the original problem: there needs to be an additional loop, one that goes through targets:

(function process (request, response) {
	var initialRequest = request.body.dataString; //Payload sent by Okta event webhook.
	var parsed = JSON.parse(initialRequest);

	try {
		for (var eventIndex = 0; eventIndex < parsed.data.events.length; eventIndex++) {
			var event = parsed.data.events[eventIndex];
			var inputs = {};

			inputs.event_type = event.eventType; // String (Type of event triggered)

			for (var targetIndex = 0; targetIndex < event.target.length; targetIndex++) {
				var target = event.target[targetIndex];

				inputs.email_address = target.alternateId; // String (Email address of suspended user)
				inputs.target_id = target.id; // String (Okta unique ID of suspended user)

				gs.debug(JSON.stringify(inputs, null, '\t'));

				if (inputs.email_address == '') {
					response.setError(new sn_ws_err.BadRequestError('Target alternateId is empty')); // Throw an error if email_address isn't present in payload
				}
				else {
					// Start Asynchronously:
					sn_fd.FlowAPI.getRunner().subflow('x_abcd_acc_repo.user_suspended__subflow').inBackground().withInputs(inputs).run(); //Trigger Suspend User subflow
				}
			}
		}
	}
	catch (ex) {
		var message = ex.getMessage();
		gs.error(message);
	}
})(request, response);

 

Also, as you can see, there is no need to write out parsed.data.events[loop] every time, one can declare a variable (I dis so defining event), assign the array element to that variable and the script becomes a bit less cluttered:

			var event = parsed.data.events[eventIndex];

View solution in original post

Vishal Birajdar
Giga Sage

Hello @shellypoeckes 

 

Can you try like below :

 

VishalBirajdar_0-1706245864945.png

 

 

/*Taking payload in variable just for demo*/
var payLoad = {
"eventType"        : "com.okta.event_hook",
 "eventTypeVersion": "1.0",
 "eventId"         : "1234",
 "data"            : {
                        "events": [
                                    {
                                        "uuid": "1234-56789",
                                        "published": "2024-01-19T04:25:30.118Z",
                                        "eventType": "user.lifecycle.suspend",
                                        "version": "0",
                                        "displayMessage": "Suspend Okta user",
                                        "severity": "INFO",
                                        "client": {
                                                    "userAgent": null,
                                                    "geographicalContext": null,
                                                    "ipChain": []
                                                    },
                                        "device": null,
                                        "actor": {
                                                    "id": "1234xyz",
                                                    "type": "SystemPrincipal",
                                                    "alternateId": "system@okta.com",
                                                    "displayName": "Okta System",
                                                    "detailEntry": null
                                                    },
                                        "outcome": {
                                        "result": "SUCCESS",
                                        "reason": null
                                        },
                                        "target": [
                                                     {
                                                        "id": "00u45mfnjjZCmyVjP1d7",
                                                        "type": "User",
                                                        "alternateId": "Joe.Doe@test.com",
                                                        "displayName": "Joe Doe",
                                                        "detailEntry": null
                                                        }
                                                ],
                                        "transaction": {
                                        "type": "JOB",
                                        "id": "ij1cevphd6cFrdHjP1d7",
                                        "detail": {}
                                        }
                                    }
                                ]
                        }
}

/* Dot walk to events & get events data */
var eventData = payLoad.data.events;

/* Loop through eventData */
for(var i=0 ; i<eventData.length ;i++){
    /* Get desired data */
    gs.print('Acrtor . Alternate Id=' + eventData[i].actor.alternateId);

    gs.print('Event Type=' + eventData[i].eventType);

    gs.print('Targer . Id =' + eventData[i].target[0].id);  // If target array have multiple values then you can loop throguh it 
    
}

/*You can use your logic in for loop*/

 

Vishal Birajdar
ServiceNow Developer

I know one thing, and that is that I know nothing.
- Socrates

View solution in original post

5 REPLIES 5

Sandeep Rajput
Tera Patron
Tera Patron

@shellypoeckes You should not use same loop variable to access the target array as the number of objects inside the events array and target array may be different.

 

E.g. The events array may have 7 objects in it and the target array may have 2 objects for an event object which is at index 3 in events array, the loop will run for the 3rd time it will try to access the target[3] here the script will crash due to accessing an index which is beyond array's current indexes.

 

Use a separate for loop for accessing the target array object.

 

Hope this helps.

Hi @Sandeep Rajput 

 

Can you please explain?  Here's my code.

 

(function process( /*RESTAPIRequest*/ request, /*RESTAPIResponse*/ response) {

var initialRequest = request.body.dataString; //Payload sent by Okta event webhook.
var parsed = JSON.parse(initialRequest);
try {
for (var loop = 0; loop < parsed.data.length; loop++)
{
var inputs = {};
inputs['email_address'] = parsed.data.events[loop].target[0].alternateId; // String (Email address of suspended user)
inputs['event_type'] = parsed.data.events[loop].eventType; // String (Type of event triggered)
inputs['target_id'] = parsed.data.events[loop].target[0].id; // String (Okta unique ID of suspended user)

if (inputs['email_address'] == '') {
response.setError(new sn_ws_err.BadRequestError('Target alternateId is empty')); //Throw an error if email_address isn't present in payload
} else {
// Start Asynchronously:
sn_fd.FlowAPI.getRunner().subflow('x_abcd_acc_repo.user_suspended__subflow').inBackground().withInputs(inputs).run(); //Trigger Suspend User subflow
}
}
} catch (ex) {
var message = ex.getMessage();
gs.error(message);
}
})(request, response);

There is an error in your code: the for loop variable needs to be checked against parsed.data.events.length not parsed.data.length.

As for the original problem: there needs to be an additional loop, one that goes through targets:

(function process (request, response) {
	var initialRequest = request.body.dataString; //Payload sent by Okta event webhook.
	var parsed = JSON.parse(initialRequest);

	try {
		for (var eventIndex = 0; eventIndex < parsed.data.events.length; eventIndex++) {
			var event = parsed.data.events[eventIndex];
			var inputs = {};

			inputs.event_type = event.eventType; // String (Type of event triggered)

			for (var targetIndex = 0; targetIndex < event.target.length; targetIndex++) {
				var target = event.target[targetIndex];

				inputs.email_address = target.alternateId; // String (Email address of suspended user)
				inputs.target_id = target.id; // String (Okta unique ID of suspended user)

				gs.debug(JSON.stringify(inputs, null, '\t'));

				if (inputs.email_address == '') {
					response.setError(new sn_ws_err.BadRequestError('Target alternateId is empty')); // Throw an error if email_address isn't present in payload
				}
				else {
					// Start Asynchronously:
					sn_fd.FlowAPI.getRunner().subflow('x_abcd_acc_repo.user_suspended__subflow').inBackground().withInputs(inputs).run(); //Trigger Suspend User subflow
				}
			}
		}
	}
	catch (ex) {
		var message = ex.getMessage();
		gs.error(message);
	}
})(request, response);

 

Also, as you can see, there is no need to write out parsed.data.events[loop] every time, one can declare a variable (I dis so defining event), assign the array element to that variable and the script becomes a bit less cluttered:

			var event = parsed.data.events[eventIndex];

Vishal Birajdar
Giga Sage

Hello @shellypoeckes 

 

Can you try like below :

 

VishalBirajdar_0-1706245864945.png

 

 

/*Taking payload in variable just for demo*/
var payLoad = {
"eventType"        : "com.okta.event_hook",
 "eventTypeVersion": "1.0",
 "eventId"         : "1234",
 "data"            : {
                        "events": [
                                    {
                                        "uuid": "1234-56789",
                                        "published": "2024-01-19T04:25:30.118Z",
                                        "eventType": "user.lifecycle.suspend",
                                        "version": "0",
                                        "displayMessage": "Suspend Okta user",
                                        "severity": "INFO",
                                        "client": {
                                                    "userAgent": null,
                                                    "geographicalContext": null,
                                                    "ipChain": []
                                                    },
                                        "device": null,
                                        "actor": {
                                                    "id": "1234xyz",
                                                    "type": "SystemPrincipal",
                                                    "alternateId": "system@okta.com",
                                                    "displayName": "Okta System",
                                                    "detailEntry": null
                                                    },
                                        "outcome": {
                                        "result": "SUCCESS",
                                        "reason": null
                                        },
                                        "target": [
                                                     {
                                                        "id": "00u45mfnjjZCmyVjP1d7",
                                                        "type": "User",
                                                        "alternateId": "Joe.Doe@test.com",
                                                        "displayName": "Joe Doe",
                                                        "detailEntry": null
                                                        }
                                                ],
                                        "transaction": {
                                        "type": "JOB",
                                        "id": "ij1cevphd6cFrdHjP1d7",
                                        "detail": {}
                                        }
                                    }
                                ]
                        }
}

/* Dot walk to events & get events data */
var eventData = payLoad.data.events;

/* Loop through eventData */
for(var i=0 ; i<eventData.length ;i++){
    /* Get desired data */
    gs.print('Acrtor . Alternate Id=' + eventData[i].actor.alternateId);

    gs.print('Event Type=' + eventData[i].eventType);

    gs.print('Targer . Id =' + eventData[i].target[0].id);  // If target array have multiple values then you can loop throguh it 
    
}

/*You can use your logic in for loop*/

 

Vishal Birajdar
ServiceNow Developer

I know one thing, and that is that I know nothing.
- Socrates