Json Payload Transform

Hi,

I have a JSON object Array which has nearly 150  fields which comes in request, i need to overwrite  values of ~10 fields. Normal approach of extracting 150 fields and assigning to 150 variables and using them is an hectic task, is there any way i can only modify 10 values and remaining fields should remain un changed.

Also tried, Set payload with entire payload and take values using JSON path directly but did not workout.

Thanks.

Solved Solved
0 8 863
1 ACCEPTED SOLUTION

I think you want to

  • iterate through an array of JS objects
  • for each JS object, transform the object, removing fields that have blank strings as values.
  • And these objects are not "flat". In other words the field values may themselves be JS hashes (objects), and the same "remove blank values" should apply there. Which means you need recursion. You need logic that "walks the object graph".

This isn't related to Apigee. Of course you're doing it within the scope of an Apigee proxy, but this is just a JavaScript question.

The iteration is pretty simple. Since we're doing a transform we'll use the "map" function on the JS array.

 

var newObj = sourceObj.map(function(oneObject) { 
  // transform that one object
});

 

The output of that will be a new array with different elements.  Each inner element has been transformed.

Now, regarding the "transform one object" task, If each object were a "flat hash", in other words, just a set of fields with simple string values, like this:

 

{
  "field1" : "value1",
  "field2" : "",
  "field3" : "value3"
}

 

..then the "transform one object" would be pretty simple too. You just need to iterate over the fields in the object and remove those that are blanks.

 

Object.keys(obj).forEach( function(fieldname) { 
   if (obj[fieldname] === "") { delete obj[fieldname]; } 
} ) ; 

 

But you have more complex data. Your data may have nested objects. For that you need to use recursion.

The following code works with the data you provided. If your data is more complex than that you might need to adjust the code to handle other cases.

 

var what = Object.prototype.toString;

function recursiveDelete(obj, testFn) {
  var wo = what.call(obj);

  if (wo == '[object Object]') {
    Object.keys(obj).forEach(function(key){
      if (testFn(obj[key])) {
        delete obj[key];
      }
      else if (what.call(obj[key]) == '[object Object]') {
        recursiveDelete(obj[key], testFn);
      }
    });
  }
  return obj;
}

function isBlank(obj) {
  return (obj === '');
}

var source = JSON.parse(context.getVariable('request.content'));
// source is an array

var newObj =
  source.map(function(currentValue){
      return recursiveDelete(currentValue, isBlank);
    });
context.setVariable('request.content', JSON.stringify(newObj));

 

View solution in original post

8 REPLIES 8

I would use the JavaScript policy for that task.   For example, if it is the content of the 'response' message, then this JavaScript would modify that response: 

// parse the context variable into a JS-scoped variable 
var c = JSON.parse(context.getVariable('response.content'));

// the variable c now holds the entire JSON

// remove a field
delete c.fieldToRemove;

// add a field
c.timestamp = (new Date()).toISOString(); 

// modify a field
c.id = "ID-" + c.id; 

// all other fields remain unchanged.

// write the modified version back to the message body
context.setVariable('response.content', JSON.stringify(c));

 

Hey, Thanks for the quick response, The above one looks fine but if i want to run loop and delete empty fields in JSON payload how it would be.

I don't know what you mean by "empty".  I guess maybe you want to delete the JSON field, if the value is null?  Maybe you could give me an example of the JSON Payload, in the BEFORE case, and the desired AFTER case. 

In any case, the JavaScript policy allows loops. Here's an example of processing an array. 

 

var c = JSON.parse(context.getVariable('response.content'));

if (c.array) {
  var newArray = c.array.filter(function(item, index) {
    return !(item.isPrivate);
  });
  c.array = newArray;
}
context.setVariable('response.content', JSON.stringify(c));

 

Hi, Yes you are right, Please find the example of before and after case. 

Before: 

{

"name": "jolly",

"lastname":"LLB",

"middlename": ""

}

 

After:

{

"name": "jolly",

"lastname":"LLB",

}

This i want to run on array of json object payload.

 

Thanks

ok so you need

delete c.middlename;

...with a JSON.parse() before and JSON.stringify() after, as I showed in my examples. Have you tried this?

Hey, Thanks for reply, please find the below payload on which i want to remove empty keys, 

[
{
"field1": {
"field11": "RTP",
"field12": "string",
"field13": {
"Name": "hello",
"Branch": ""
},

}
},

{
"field2": {
"field21": {
"field211": "string",
"field222": "",
"field223": 19996
},
"field22": {
"hhhhhh": 1,
"ttyyyhh": "string",
"tenat": "",
"user": "string"
}

}
]

 

 

This is sample structure, in field 1 & field 2 i have ~100 keys.

Tried this :

var inputData = context.getVariable("request.content");

var outputData = inputData.filter(function(x) { return x !== null });

context.setVariable("response.content",outputData);

 

but failed tried for loop as well but failed. please suggest feasible solution.

 

Thanks

I think you want to

  • iterate through an array of JS objects
  • for each JS object, transform the object, removing fields that have blank strings as values.
  • And these objects are not "flat". In other words the field values may themselves be JS hashes (objects), and the same "remove blank values" should apply there. Which means you need recursion. You need logic that "walks the object graph".

This isn't related to Apigee. Of course you're doing it within the scope of an Apigee proxy, but this is just a JavaScript question.

The iteration is pretty simple. Since we're doing a transform we'll use the "map" function on the JS array.

 

var newObj = sourceObj.map(function(oneObject) { 
  // transform that one object
});

 

The output of that will be a new array with different elements.  Each inner element has been transformed.

Now, regarding the "transform one object" task, If each object were a "flat hash", in other words, just a set of fields with simple string values, like this:

 

{
  "field1" : "value1",
  "field2" : "",
  "field3" : "value3"
}

 

..then the "transform one object" would be pretty simple too. You just need to iterate over the fields in the object and remove those that are blanks.

 

Object.keys(obj).forEach( function(fieldname) { 
   if (obj[fieldname] === "") { delete obj[fieldname]; } 
} ) ; 

 

But you have more complex data. Your data may have nested objects. For that you need to use recursion.

The following code works with the data you provided. If your data is more complex than that you might need to adjust the code to handle other cases.

 

var what = Object.prototype.toString;

function recursiveDelete(obj, testFn) {
  var wo = what.call(obj);

  if (wo == '[object Object]') {
    Object.keys(obj).forEach(function(key){
      if (testFn(obj[key])) {
        delete obj[key];
      }
      else if (what.call(obj[key]) == '[object Object]') {
        recursiveDelete(obj[key], testFn);
      }
    });
  }
  return obj;
}

function isBlank(obj) {
  return (obj === '');
}

var source = JSON.parse(context.getVariable('request.content'));
// source is an array

var newObj =
  source.map(function(currentValue){
      return recursiveDelete(currentValue, isBlank);
    });
context.setVariable('request.content', JSON.stringify(newObj));

 

Hi,

By combining things, some how i am able to achieve what i want . Thanks for the support.