Set an environment variable for each item/index of some array

My question:
There are two parts to this question setting environment vars based on the size of some array but then using those environment vars in a post request

Details (like screenshots):

//Get the size of the Zone array, how many zones

const requestBody = JSON.parse(pm.request.body.raw)

const numOfZones = requestBody.zones.length;

const zoneConfigIDs =

//Generate UUIDs for the id key for each zone for as many zones as there are
for (let i = 0; i<numOfZones; i++)
{
// pm.environment.set(“zoneConfigID”,uuid.v4().toUpperCase())
// zones[i].id = uuid.v4().toUpperCase()
const zoneConfigID = uuid.v4().toUpperCase()
zoneConfigIDs.push(zoneConfigID)
pm.environment.set(“zoneConfigID”,JSON.stringify(zoneConfigIDs[i]))
console.log(zoneConfigIDs[i])
}

Now using the env. var(s) created from pre-request in the actual post call body:

“zones”: [
{
“id”: “{{zoneConfigID}}”
},
{
“id”: “{{zoneConfigID}}”,
}
]
How I found the problem:
with the few things i tried I either get the last UUID generated for all id fields (when they need to be unique per zone) or I get the array of UUIDs as string [“uuid1”,“uuid2”] or i get the literal string {{zoneConfigID_{$i}}}

I’ve already tried:

I have tried to use “id”: “{{zoneConfigID_${i}}}”
and also in the pre-script while setting the env. var

I wouldn’t set the values as environment variables (as there could be a lot based on the size of the array).

But you can update the values within the body with something similar to the following in a pre-request script.

No need to mess around with array indexes.

const body = JSON.parse(pm.request.body.raw);
// console.log(body);

body.zones.forEach(zone => {
    zone.id = pm.variables.replaceIn("{{$guid}}");
    // console.log(zone.id)
});

pm.request.body.raw = body;
// console.log(pm.request.body.raw)
1 Like

First thanks for the reply,

I agree that the size of the array could mean a lot of env. vars, I actually have a number of working solutions similar to what you suggested but I wanted to learn if there is a way I could simply set a single env. var with a rotating index

something like:
pm.environment.set(zoneConfigID_${i}, zoneConfigID);

without having to manipulate the raw payload body, the following works but I am making changes to the raw payload body:

// // Generate UUIDs for the id key for each zone for as many zones as there are

// for (let i = 0; i < zonesArraySize; i++) {

// zonesArray[i].id = pm.variables.replaceIn(uuid.v4().toUpperCase());

// }

// // Update the request body with the modified zones array

// pm.request.body.raw = JSON.stringify(requestBody, null, 2);

I am approaching this the same way we can do something like this:

var zoneName = “Zone 1”

pm.environment.set(“zoneName”, zoneName)

and then reference that directly in the json payload body

{
“name”: “{{zoneName}}”,

}

Your original post had an example body that included multiple objects, each with their own “id”.

I assumed that you needed to ensure each id was unique and its a single POST request sending all of those id’s at the same time.

Therefore, the following won’t work as the variable name is not unique and will get get overwritten each time with the latest value.

pm.environment.set(“zoneConfigID”,JSON.stringify(zoneConfigIDs[i]))

You would have to turn it on its head, and make the variable name dynamic as well as the value, and then reference it by the correct variable name in the body.

I can’t see how you would have a single environment variable that could be used.

You might need to explain the rotating index concept, as I’m not sure what you mean by that. Not in a single POST request. It could be done if it was multiple POST requests, each with a single zone\ID each time using the JavaScript array.shift() method and setNextRequest (to keep looping through the same request).

Do you know how many zones\id’s will be sent each time?

First sorry for not getting back sooner, and I appreciate your help

Yes that’s correct multiple IDs and each one needs to be unique. The single variable was getting overwritten you’re right in that aspect.

This is a configuration end-point, so it has to be done in a single POST otherwise I need to check if there is support for PUT or UPDATE in order to make multiple calls and in each call have a single zone ID

I think for now I have a working solution, which requires the use of

pm.request.body.raw = JSON.stringify(requestBody, null, 2);

which is altering or updating the request body directly

and 2 options

either using the
pm.environment.set(zoneConfigID_${i}, zoneConfigID);
and with that reference the actual index in the request body so something like

“Id”:{{zoneConfigID_0}}, and _1 and so on

or

use the replaceIn function() and directly access the json keys for example body.zoneConfig.Id but of course make an array of the zone IDs size and iterate over them

Like I said I have a working solution I just wanted something simpler like a typical pm.environment.set() but I guess because we have the same key multiple times that won’t be as simple as we normally set environment variables

This has been informational and helped me understand how to work with dynamic environment variables and more so when there are arrays involved

actually @michaelderekjones I am in this situation because I wasn’t able to use {{$guid}} postman built in function directly (although very handy) because the end-point expects uppercase

I tried to use {{$guid.toUpperCase())}} but doesn’t seem to work so that’s why I had to write a pre-request script otherwise i could have used the {{$guid}} directly in the json payload body without the need for any scripting

unless you know of a way

You can’t use the toUpperCase() JavaScript function in the body (as you can’t have code in the body).

You can amend the pre-request script I provided to change it to uppercase.

const body = JSON.parse(pm.request.body.raw);
console.log(body);

body.zones.forEach(zone => {
    zone.id = (pm.variables.replaceIn("{{$guid}}")).toUpperCase();
    console.log(zone.id)
});

pm.request.body.raw = body;
console.log(pm.request.body.raw)

right makes sense

Cool thanks for the help

here is my final working solution for other’s benefits:

// Get the size of the zones array in the request body, how many zones
const requestBody = JSON.parse(pm.request.body.raw);
const zonesArray = requestBody.zones;
const zonesArraySize = zonesArray.length;

console.log(zonesArray);

// Generate UUIDs for the id key for each zone for as many zones as there are
for (let i = 0; i < zonesArraySize; i++) {
zonesArray[i].id = pm.variables.replaceIn(uuid.v4().toUpperCase());
//Now do the Modules inside each zone
const modulesArray = zonesArray[i].modules

const modulesArraySize = modulesArray.length

for (let j = 0; j < modulesArraySize; j++)
{
modulesArray[j].id = pm.variables.replaceIn(uuid.v4().toUpperCase())
}
}

// Update the request body with the modified zones array
pm.request.body.raw = JSON.stringify(requestBody, null, 2);

Here is an alternative method:

/*

This method uses an env var as an indexed array

but would need to hardcode the index in the payload zoneConfigID_0, zoneConfigID_1…etc.

*/

// Get the request body as a string

// const requestBody = pm.request.body.raw;

// // Parse the request body as JSON

// const requestBodyJson = JSON.parse(requestBody);

// // Determine the size of the zones array

// const zonesCount = requestBodyJson.zones.length;

// // Generate UUIDs for each zoneConfigID and set environment variables

// for (let i = 0; i < zonesCount; i++) {

// const zoneConfigID = uuid.v4().toUpperCase();

// pm.environment.set(zoneConfigID_${i}, zoneConfigID);

// }

// // Log the generated UUIDs

// console.log(pm.environment.toObject());