This article describes an advanced data transformation solution for Apigee Integration using the Apps Script task and JSMapr library for transforming JSON data.
Apigee Integration, integration platform that helps connect existing data and applications, and surface them as easily accessible APIs (For data transformation in ApigeeX (API management) refer to Shaping, accessing, and converting messages)
Apps Script Task, a cloud-based JavaScript platform that lets you integrate with and automate tasks across Google products. (Refer to Data Mapping task for simple data mapping needs)
JSMapr, open source Javascript based JSON transformation library (Other Apps Script libraries can also be used)
Consider an input JSON that looks as follows:
{
"fName": "Fred",
"lName": "Smith",
"addresses": [
{
"addr": "177 Pine St",
"city": "San Jose",
"state": "CA",
"zip": 95120,
"addressType": "HOME"
},
{
"addr": "10 S Almaden Blvd",
"city": "San Jose",
"state": "CA",
"zip": 95113,
"addressType": "WORK"
}
],
"username": "fsmith",
"child": "Ryan"
}
and needs to be converted to the following JSON format:
{
"firstName": "Fred",
"lastName": "Smith",
"addresses": [
{
"streetAddress": "177 Pine St",
"city": "San Jose",
"state": "CA",
"zip": "95120",
"addressType": "HOME"
},
{
"streetAddress": "10 S Almaden Blvd",
"city": "San Jose",
"state": "CA",
"zip": "95113",
"addressType": "WORK"
}
],
"username": "fsmith",
"children": [ "Ryan" ]
}
A handful of changes are involved here.
Such changes are often needed in integration flows including but not limited to
JSMapr is a JavaScript library for transforming JSON objects. It is a self contained library with no other dependencies and can be used in both JavaScript (Apps Script) and node.js environments.
JSMapr helps express transformation rules in a declarative style and reduces the amount of code that needs to be written to achieve similar results with JavaScript.
For example:
JSMapr.MAKEARRAY("/children"),
instructs that "children" attribute be converted into an single element Array.
JSMapr provides a wealth of operations for transformation
ADD
DEL
COPY
MOVE
TOSTRING
STRINGIFY
MAKEARRAY
ADDTOARRAY
MOVETOARRAY
MAP1
MAPEACH
FUNC1
FUNCEACH
SORTARRAY
EXEC
IFEXISTS
IFEQUAL
IFTYPE
IF
IFFUNC
LOCSEPARATOR
Apigee Integration offers an Apps Script based Apps Script task that is useful when you want to run custom scripts or reuse existing scripts in your integration.
You can use JSMapr in Apps Script for JSON data transformation needs. Follow the steps below to setup a sample.
function run() {
// Read an integration variable
var employee = AppsScriptTask.getTaskParameter('employee');
var myMap = [
// change field names
JSMapr.MOVE("/lName", "/lastName"),
JSMapr.MOVE("/fName", "/firstName"),
JSMapr.MOVE("/child", "/children"),
JSMapr.TOSTRING("/zip1"),
// change children to an array
JSMapr.MAKEARRAY("/children"),
// force zips to be strings and change street address name
JSMapr.MAPEACH("/addresses",
[
JSMapr.TOSTRING("/zip"),
JSMapr.MOVE("/addr", "/streetAddress")
]
)
];
var mapr = new JSMapr();
mapr.setMapCommands(myMap);
var newEmployee = mapr.map(employee);
AppsScriptTask.setIntegrationVariable('employee-new', newEmployee);
}
function testSample() {
// Create a new request
let req = AppsScriptTaskTest.createNewTestRequest('json-test');
var employee = {
"fName": "Fred",
"lName": "Smith",
"addresses": [
{
"addr": "177 Pine St",
"city": "San Jose",
"state": "CA",
"zip": 95120,
"addressType": "HOME"
},
{
"addr": "10 S Almaden Blvd",
"city": "San Jose",
"state": "CA",
"zip": 95113,
"addressType": "WORK"
}
],
"username": "fsmith",
"child": "Ryan"
};
// Add a task parameter that references a JSON integration variable
AppsScriptTaskTest.setEventParameterAndCreateReference(req, "employee", "employee", employee);
// out-dated
// AppsScriptTaskTest.setIntegrationVariableAndCreateReference(req, "emp", "employee", {name:"snape", age:35});
let res = AppsScriptTaskTest.runTest(req, executeScript);
var expectedOutput = {
"addresses": [{
"city": "San Jose",
"state": "CA",
"zip": "95120",
"addressType": "HOME",
"streetAddress": "177 Pine St"
}, {
"city": "San Jose",
"state": "CA",
"zip": "95113",
"addressType": "WORK",
"streetAddress": "10 S Almaden Blvd"
}],
"username": "fsmith",
"lastName": "Smith",
"firstName": "Fred",
"children": ["Ryan"]
}
// Check the response for the expected integration variable and its corresponding values
console.log("test output" + JSON.stringify(AppsScriptTask.getTaskParameter("employee-new"), null, 2));
AppsScriptTaskTest.containsParameterValue(res, "employee-new", expectedOutput);
// out-dated
// AppsScriptTaskTest.containsIntegrationVariableWithValue(res, "employee-new", expectedOutput);
}
{
"fName": "Fred",
"lName": "Smith",
"addresses": [
{
"addr": "177 Pine St",
"city": "San Jose",
"state": "CA",
"zip": 95120,
"addressType": "HOME"
},
{
"addr": "10 S Almaden Blvd",
"city": "San Jose",
"state": "CA",
"zip": 95113,
"addressType": "WORK"
}
],
"username": "fsmith",
"child": "Ryan"
}
{
"firstName": "Fred",
"lastName": "Smith",
"addresses": [
{
"streetAddress": "177 Pine St",
"city": "San Jose",
"state": "CA",
"zip": "95120",
"addressType": "HOME"
},
{
"streetAddress": "10 S Almaden Blvd",
"city": "San Jose",
"state": "CA",
"zip": "95113",
"addressType": "WORK"
}
],
"username": "fsmith",
"children": [ "Ryan" ]
}
Apigee Integration receives the input JSON, invokes Apps Script task to perform the transformation using JSMapr and returns the output JSON.
The above sample is a simple scenario involving a single JSON input variable being transformed into a output JSON variable. This can be embedded in a complex integration flow or a complex Apps Script involving multiple steps.