I think what you want to to is shred the values in the JSON payload and set context variables that can be used by other policies.
This may be obvious to some, and less obvious to others: Variables that are known within the JavaScript callout are not accessible within the request flow context. For example, suppose this is the JS code:
var jsonObject = { "foo" : "bar" };
The name “jsonObject” is known only within the scope of the JavaScript execution. It is not accessible in an AssignMessage policy, or any other policy, or any Conditions that follow the JavaScript step.
There IS a way to read and write context variables from within the logic for a JavaScript step - that is with context.getVariable() and context.setVariable().
In the simplest case, suppose you want to set a guid, from within the JavaScript step, and have that guid be accessible to Conditions, or future AssignMessage policies. You can do this:
var guid = "4F825E81-C498-4943-9C1F-3578DE3E70C5";
context.setVariable("my.guid.variable", guid);
And subsequent policies will be able to reference the variable named “my.guid.variable” to see that string.
Maybe your requirement is a bit more advanced. Maybe you’d like to extract every field in any particular JSON payload and “export” that to a context variable. So, for this JSON:
{ "foo" : "bar", "id" :7, "ready" : true }
You might want three context variables representing each one.
This is also possible with a recursive function applied over the json graph. It might look something like this:
var jsonObject = JSON.parse(context.getVariable('request.content'));
walkObj(jsonObject,
function(name, value) {
context.setVariable(name, value);
});
Basically that says “for every property in the json, set a context variable.” But what is this “walkObj” function? it’s basically an object analogue to Array.prototype.forEach . Here’s what it looks like:
// walkObj.js
var what = Object.prototype.toString;
function walkObj(obj, path, fn) {
if ( ! fn && typeof path == 'function') {
fn = path;
path = 'json';
}
var wo = what.call(obj), p;
path = path || '';
if (wo == "[object Object]") {
Object.keys(obj).forEach(function(key){
var item = obj[key], w = what.call(item);
var pathelts = path.split('.');
pathelts.push(key);
var newpath = pathelts.join('.');
if (w == "[object Object]" || w == "[object Array]") {
walkObj(item, newpath, fn);
}
else {
fn(newpath, item);
}
});
}
else if (wo == "[object Array]") {
obj.forEach(function(item, ix){
var w = what.call(item);
var pathelts = path.split('.');
pathelts.push('['+ix+']');
var newpath = pathelts.join('.');
if (w == "[object Object]" || w == "[object Array]") {
walkObj(item, newpath, fn);
}
else {
fn(newpath, item);
}
});
}
else {
var msg = "Unknown object to covert: " + wo + "("+ JSON.stringify(obj, null, 2).slice(0, 34) +")";
//console.log(msg);
throw {error: true, message: msg };
}
}
The JS policy configuration looks like this:
<Javascript name='JS-ExtractInboundRequest' timeLimit='200' >
<Properties>
<Property name='prefix'>json</Property>
</Properties>
<IncludeURL>jsc://walkObj.js</IncludeURL>
<ResourceURL>jsc://extractInboundRequest.js</ResourceURL>
</Javascript>
Let’s try it. Running that policy on the inbound payload like this:
{ "foo" : "bar", "id" :7, "ready" : true }
results in these context variables being set:
| name of variable |
value |
| json.foo |
“bar” |
| json.id |
7 |
| json.ready |
true |
You can also pass in more complex JSON payloads. For example, given this input:
{
"name": "rooms/AAAAra-BYE/chats/qo4NQAAAAAE/messages/Ko4NQABBAE",
"sender": {
"name": "users/1138844348030",
"displayName": "Dino Chiesa",
"avatarUrl": "https://foo.bar.bam.com/-cBWaVITMntw/AAAAAAAAAAI/AAAAAAAA/hxGRhDY/photo.jpg",
"email": "dchiesa@google.com"
},
"createTime": "2017-03-07T23:53:04.504207Z",
"text": "/jira MGMT-3909"
}
The resulting context variables are:
Please find attached a working example proxy. Import and deploy it and you can see it working.
extract-json-apiproxy.zip