Hi, I need to achieve the following:
1.For request body transformation as shown below –
{
"abc_def": "1",
"variables": {
"AbcDef": "xxxxxxxxxxxxxxxxxxxx",
"A": "xxxxxxxxxxxxxx",
"GhiJkl”: “xxxxxxxxxxxxxx",
}
}
We want to follow the standard case pattern(here Camel Case) for passing the variables like –
{
"abc_Def": "1",
"variables": {
"abcDef": "xxxxxxxxxxxxxxxxxxxx",
"a": "xxxxxxxxxxxxxx",
"ghiJkl”: “xxxxxxxxxxxxxx",
}
}
Currently, we are using JavaScript to loop through the JSON payload and using KVM to map the proxy based variables and target based variables. As, the number of variables scale up, the KVM structuring will be mpre complex . Can you suggest a better way to do this...
Also can we pass dynamic values in Parameter reference in KVM policy like –
Variable1, Variable2, Variable3 - for all these key names <Parameter ref=” Variable*”/> ?
Is there a set of rules you can follow?
It looks to me that the rules for converting property names are:
That's pretty easy, isn't it? You don't need a KVM for that. This works:
function pascalCaseToCamelCase(str) { return str.charAt(0).toLowerCase() + str.split('_').map(function(s){ return s.charAt(0).toUpperCase() + s.slice(1); }).join('_').slice(1); }
And here are some tests:
var tests = { "abc_def": "abc_Def", "variables": "variables", "AbcDef": "abcDef", "A": "a", "GhiJkl": "ghiJkl" }; var counts = {PASS:0, FAIL:0}; Object.keys(tests).forEach(function(testcase){ var actualResult = pascalCaseToCamelCase(testcase); var expectedResult = tests[testcase]; var resolution = (actualResult === expectedResult)?"PASS":"FAIL"; console.log("%s : %s %s", testcase, actualResult, expectedResult, resolution); counts[resolution]++; }); console.log("\n==================================================================\n"); Object.keys(counts).forEach(function(r){ console.log("%s : %d", r, counts[r]); });
The results I see:
abc_def : abc_Def abc_Def PASS variables : variables variables PASS AbcDef : abcDef abcDef PASS A : a a PASS GhiJkl : ghiJkl ghiJkl PASS ================================================================== PASS : 5 FAIL : 0
You will probably want to write lots more tests to make sure the converter does what you want in all edge cases.
Thanks for the response,the given answer suffice our need of having properties with proper naming convention.
But we do have a more complex transformation between the frontend and backend parameters.
For example:
While sending a request payload,the frontend parameters would be id and name as follows:
{
"id":"123",
"name":"xyz"
}
But,the backend recognize parameters "sys_id" , "sys_name".
So we need to map, id --> sys_id and name --> sys_name before the request is sent to backend. And this JSON varies based on some conditions and JSON can have many level of nested of objects.
Also,we would have this transformation applied to more than one APIs.
Would KVM would be the the recommmended way to do so? If not ,kindly suggest a better way to achieve the given scenario.
Yes, I think in that case a KVM storing a set of paths to map would be good.
For example if the JSON payload is
{ "foo": "1", "variables": { "name": "xxxxxxxxxxxxxxxxxxxx", "id": "xxxxxxxxxxxxxx" } }
Then you would want something like this in the KVM:
{"variables": { "id" : "sys" } }
And you'd need some JavaScript to walk the payload and modify it according to the map stored in the KVM.
This might sound exotic but it's really just name replacement and it's easy and fast with a recursive function in a regular JavaScript callout.
For the recursive walk, look here.
Here's an example that runs in nodejs from the command line:
// =================================================================== // mock context var contextVars = { }; var context = { getVariable : function(name) { var value = contextVars[name]; console.log('GET %s = %s', name, value); return value; }, setVariable: function (name, value) { console.log('SET %s := %s', name, value); contextVars[name] = value; } }; // ================================================================= var source = { "foo": "1", "variables": { "name": "xxxxxxxxxxxxxxxxxxxx", "id": "xxxxxxxxxxxxxx" } }; var mapRules = {"variables": { "id" : "sys_id" } }; var walkObj = require('./walkObj.js'); console.log("RULES"); console.log(JSON.stringify(mapRules)); walkObj(mapRules, 'rule', function(name, value) { context.setVariable(name, value); }); console.log("BEFORE"); console.log(JSON.stringify(source, null, 2) + '\n'); walkObj(source, '', function(fullpath, itemvalue, oldkey, obj) { var ruleName = 'rule.' + fullpath; var substitution = context.getVariable(ruleName); if (substitution) { obj[substitution] = itemvalue; delete obj[oldkey]; } }); console.log("AFTER"); console.log(JSON.stringify(source, null, 2) + '\n');
and here is the output showing the results:
$ ./mapProperties.js RULES {"variables":{"id":"sys_id"}} SET rule.variables.id := sys_id BEFORE { "foo": "1", "variables": { "name": "xxxxxxxxxxxxxxxxxxxx", "id": "xxxxxxxxxxxxxx" } } GET rule.foo = undefined GET rule.variables.name = undefined GET rule.variables.id = sys_id AFTER { "foo": "1", "variables": { "name": "xxxxxxxxxxxxxxxxxxxx", "sys_id": "xxxxxxxxxxxxxx" } }
That code won't run "as is" within a JS callout. To get it to run within a JS callout, You would need to:
But it shows the principle:
User | Count |
---|---|
1 | |
1 | |
1 | |
1 | |
1 |