Handling Null Values for Pronouns in target source HTTP UPDATE Operation

@lalithajay
Since you already have a Before Provisioning rule on this source (SailPoint’s docs call it the Web Services Before Operation Rule), that’s the right place to fix this rather than the JSON template, and it can handle both your null and empty-string cases in one pass.

Worth separating those two cases first, since they’re probably not hitting the same mechanism. @MattUribe point that ISC drops AttributeRequests with no value from the plan is confirmed behavior, from this thread about a different attribute, and that’s already the outcome you want for a true null. An empty string is different, “” is still a value, so there’s a real chance ISC keeps that AttributeRequest in the plan instead of omitting it, which would explain why both null and empty string are producing the same 400 for you even though only one of them should be getting dropped automatically.

The fix is to make your rule handle both the same way: look up the Pronouns AttributeRequest on the AccountRequest, and if its value is null or an empty string, remove it from the plan so it collapses into the same “no value, don’t touch the target” behavior ISC already applies correctly to true nulls.

import sailpoint.object.ProvisioningPlan.AccountRequest;
import sailpoint.object.ProvisioningPlan.AttributeRequest;

for (AccountRequest accountRequest : Util.iterate(provisioningPlan.getAccountRequests())) {
    AttributeRequest pronounsReq = accountRequest.getAttributeRequest("Pronouns");
    if (pronounsReq != null) {
        Object value = pronounsReq.getValue();
        if (value == null || "".equals(value)) {
            accountRequest.remove(pronounsReq);
        }
    }
}

That mirrors the corrected pattern in this thread on removing an AttributeRequest from a Before Provisioning rule, just with a null/empty check instead of the identity-type condition they were using.

If that doesn’t fully solve it, worth knowing this rule type is also handed requestEndPoint directly, which per SailPoint’s documentation already contains the built request body as JSON, so you can inspect and correct it directly as a second lever in the same rule if the plan-side fix above turns out to run too late to affect what actually gets sent:

Map body = requestEndPoint.getBody();
Map jsonMap = JsonUtil.toMap((String) body.get("jsonBody"));
Object pronouns = jsonMap.get("Pronouns");
if (pronouns == null || "".equals(pronouns)) {
    jsonMap.remove("Pronouns");
}
body.put("jsonBody", JsonUtil.render(jsonMap));
requestEndPoint.setBody(body);
return requestEndPoint;

I don’t have a way to confirm from the docs alone whether the plan-side removal is guaranteed to happen before the body gets built or after, so I’d try the AccountRequest-level fix first since it’s the more standard pattern, and fall back to editing requestEndPoint directly if an empty Pronouns value still shows up in the outbound request.

The “x” suffix trick @MattUribe linked is solving a different problem, forcing an update through when the value hasn’t changed, not what you need here, so I’d leave that one aside.