Using FiddlerScript (JScript.Net) to change JSON response to null - json

I am using Fiddler's "FiddlerScript" to modify responses from a web server so that I can test responses in my app.
Here is my OnBeforeResponse function:
static function OnBeforeResponse(oSession: Session) {
// This code was already here, leaving it
if (m_Hide304s && oSession.responseCode == 304) {
oSession["ui-hide"] = "true";
}
// Here is new code to modify server's response
if(oSession.HostnameIs("mydomain.com") && oSession.uriContains("config")) {
// Color this response, so we can spot it in Fiddler
oSession["ui-backcolor"] = "lime";
// Convert the request body into a string
var oBody = System.Text.Encoding.UTF8.GetString(oSession.responseBodyBytes);
var j: Fiddler.WebFormats.JSON.JSONParseResult;
// Convert the text into a JSON object
// In this case our JSON root element is a dictionary (HashTable)
j = Fiddler.WebFormats.JSON.JsonDecode(oBody);
// Inside of our dictionary, we have an array (ArrayList) called "placements"
var testObject = j.JSONObject["test"];
/* Change this to different values, e.g. "0.0", 0.0, null, "", etc. */
/* This works */
testObject["consent_version"] = "";
/* This works */
testObject["consent_version"] = 0.0;
/* This works */
testObject["consent_version"] = "0.0";
/* This fails */
testObject["consent_version"] = null;
// Convert back to a byte array
var modBytes = Fiddler.WebFormats.JSON.JsonEncode(j.JSONObject);
// Convert json to bytes, storing the bytes in request body
var mod = System.Text.Encoding.UTF8.GetBytes(modBytes);
oSession.ResponseBody = mod;
}
}
I am able to set testObject["consent_version"] to any value except null. If I set this to null, Fiddler creates JSON which doesn't have any value, and the JSON is in a bad format like this:
"consent_version":,
Note that there is no value after "consent_version" and before the comma.
Does anyone know how I can use FiddlerScript (which is based on JScript.Net) to set a null value?

I know this is an old question, but I came across it trying to do the exact same thing, and finally figured it out... Hopefully this helps someone in the future.
First off, instead of setting it to null, set it to undefined. Chrome developer tools still shows it as returning as null.
Then, instead of
var modBytes = Fiddler.WebFormats.JSON.JsonEncode(j.JSONObject);
var mod = System.Text.Encoding.UTF8.GetBytes(modBytes);
oSession.ResponseBody = mod;
Use:
var modBytes = Fiddler.WebFormats.JSON.JsonEncode(j.JSONObject);
oSession.utilSetResponseBody(modBytes);
And you should be all set.
Here's a full example:
static function OnBeforeResponse(oSession: Session) {
if (m_Hide304s && oSession.responseCode == 304) {
oSession["ui-hide"] = "true";
}
if (true && (oSession.host=="domain.com") && (oSession.PathAndQuery.indexOf("/GetDataFromServer")>-1) && (oSession.oResponse.headers.ExistsAndContains("Content-Type", "json")) ){
oSession["ui-bold"]="true";
// Convert the request body into a string
oSession.utilDecodeResponse();
var oBody = System.Text.Encoding.UTF8.GetString(oSession.responseBodyBytes);
// FiddlerObject.log(oBody);
var j: Fiddler.WebFormats.JSON.JSONParseResult;
j = Fiddler.WebFormats.JSON.JsonDecode(oBody);
// FiddlerObject.log(j.JSONObject[0]["PropertyName"]);
j.JSONObject[0]["PropertyName"] = undefined;
// Convert back to a byte array
var modBytes = Fiddler.WebFormats.JSON.JsonEncode(j.JSONObject);
oSession.utilSetResponseBody(modBytes);
}
}

Related

Send unassigned JSON properties to server when using stringify i.e. retain properties name whether property value is empty/null

I have two model properties:
ng-model="category.name" mandatory field
ng-model="category.desc" optional
This is how I am sending data to the server (ASP.net)
var rdt = "{'dt':" + JSON.stringify($scope.category) + "}";
However, if an optional property has an unassigned value, the property name is not found server side and gives an error. Are there any ways to retain unassigned properties of JSON?
You have several solutions:
Solution 1: Initialize the variables in your scope for example:
$scope.category.desc = null
Solution 2: Create a function to take care of that
function ToJson(object, properties) {
var result = {};
for(var i = 0; i < properties.lenght; i++) {
var property = properties[i];
if(!object[property]) {
result[property] = null;
} else {
result[property] = object[property];
}
}
return JSON.stringify(result);
}
// And then use it like this:
var rdt = "{'dt':" + ToJson($scope.category, ["name", "desc"]) + "}";

Kettle PDI - Modified JavaScript - Json function not available

I'm using Kettle PDI 6.0 running on Windows Server 2012. I need to use the Modified Java Script Value to handle on Json object. I try something like this:
var jsondata = JSON.parse(result);
And get that:
"TypeError: Cannot find function parse in object test value test value test value test value test value test value test value test value test value test value. (script#3)"
I already try to looking for a solution on google, but not looks like that. I think that can be something wrong with my installation.
Note: I already try to use the command:
import java.util.*;
But that command is not recognized (Is not marked in bold).
I get:
missing ; before statement (script#2)
Maybe the Java functions not available.
I made my own function to resolve the problem. I will post here to help who has the same problem. If anyone want to help to solve the initial problem, I am still interested.
You can paste the code bellow on your "Modified Java Script Value" step after receive the Json response from service or get that on file. Note that you need to change the name of variables that you want to find on Json.
Result field is a Json Value.
//Script here
function findInArray(myValue, myArray){
var myResult='';
if(myArray.indexOf(myValue) > -1){
myResult = true;
} else {
myResult = false;
}
return myResult;
}
function getAttributeValue(Atribute, Object)
{
start = indexOf(Object,Atribute);
for (i= start; i < Object.length; i++)
{
if (substr(Object,i,1) == ":")
{
start_value = i+1;
break;
}
}
for (i= start_value; i < Object.length; i++)
{
end_value = i;
if (substr(Object,i,1) == ",")
{
break;
}
}
AttributeValue = replace(substr(Object, start_value, end_value-start_value),'"','');
if (indexOf(AttributeValue, "null") >= 0)
{
AttributeValue = null;
}
return AttributeValue ;
}
// Recupera Status
if (findInArray("status",result))
{
var status = getAttributeValue("status", result);
}
else
{
var status = "";
}
// Recupera _ID
if (findInArray("_id",result))
{
var mandrill_id = getAttributeValue("_id", result);
}
else
{
var mandrill_id = "";
}
// Recupera reject_reason
if (findInArray("reject_reason",result))
{
var reject_reason = replace(getAttributeValue("reject_reason", result),"}","");
}
else
{
var reject_reason = "";
}
yes, the parse json function is not available on the ex4 ecmascript of js rhino engine build in kettle, but you can handle json in kettle using eval.
var resultObj = eval('('+result+')');
//now you can iterate the foo elements of result original json
for(i=0;i< resultObj.length;i++){
Alert('foo number ' + i ' value = ' + resultObj[i].foo);
}
This is not javascript for the browser so eval is perfectly safe.

ScriptDB object size calculation

I'm trying to estimate the limits of my current GAS project. I use ScriptDB to chunk out processing to get around the 6 min execution limit. If I have an object like
var userObj{
id: //user email address
count: //integer 1-1000
trigger: //trigger ID
label: //string ~30 char or less
folder: //Google Drive folder ID
sendto: //'true' or 'false'
shareto: //'true' or 'false'
}
How would I calculate the size that this object takes up in the DB? I would like to project how many of these objects can exist concurrently before I reach the 200MB limit for our domain.
Whenever you've got a question about google-apps-script that isn't about the API, try searching for javascript questions first. In this case, I found JavaScript object size, and tried out the accepted answer in apps-script. (Actually, the "improved" accepted answer.) I've made no changes at all, but have reproduced it here with a test function so you can just cut & paste to try it out.
Here's what I got with the test stud object, in the debugger.
Now, it's not perfect - for instance, it doesn't factor in the size of the keys you'll use in ScriptDB. Another answer took a stab at that. But since your object contains some potentially huge values, such as an email address which can be 256 characters long, the key lengths may be of little concern.
// https://stackoverflow.com/questions/1248302/javascript-object-size/11900218#11900218
function roughSizeOfObject( object ) {
var objectList = [];
var stack = [ object ];
var bytes = 0;
while ( stack.length ) {
var value = stack.pop();
if ( typeof value === 'boolean' ) {
bytes += 4;
}
else if ( typeof value === 'string' ) {
bytes += value.length * 2;
}
else if ( typeof value === 'number' ) {
bytes += 8;
}
else if
(
typeof value === 'object'
&& objectList.indexOf( value ) === -1
)
{
objectList.push( value );
for( i in value ) {
stack.push( value[ i ] );
}
}
}
return bytes;
}
function Marks()
{
this.maxMarks = 100;
}
function Student()
{
this.firstName = "firstName";
this.lastName = "lastName";
this.marks = new Marks();
}
function test () {
var stud = new Student();
var studSize = roughSizeOfObject(stud);
debugger;
}

AS3 load variables from a txt file which has && formatting

I'm trying to load a txt file of variables into my AS3 project. The problem I have though seems to be down to the fact that the txt file (which is pre formatted and cannot be changed) is formatted using double amphersands... e.g.
&name=mark&
&address=here&
&tel=12345&
I'm using the following code to load the txt file
myLoader.addEventListener(Event.COMPLETE, onLoaded, false, 0, true);
myLoader.dataFormat = URLLoaderDataFormat.VARIABLES;
urlRqSend = new URLRequest(addressToTxt.txt);
public function onLoaded(e:Event):void {
trace(myLoader.data);
}
Using URLLoaderDataFormat.VARIABLES generates the following error:
Error: Error #2101: The String passed to URLVariables.decode() must be a URL-encoded query string containing name/value pairs.
If I use URLLoaderDataFormat.TEXT I can load the data successfully but I'm not able (or don't know how to) access the variables.
Would anyone have any ideas or work arounds to this please.
Thanks,
Mark
I had that kind of problem some time ago.
I suggest you to load first as a text, remove those line breaks, the extra amphersands and parse manually:
var textVariables:String;
var objectVariables:Object = new Object();
...
myLoader.addEventListener(Event.COMPLETE, onLoaded, false, 0, true);
myLoader.dataFormat = URLLoaderDataFormat.TEXT;
urlRqSend = new URLRequest(addressToTxt.txt);
public function onLoaded(e:Event):void {
textVariables = myLoader.data;
textVariables = textVariables.split("\n").join("").split("\r").join(""); // removing line breaks
textVariables = textVariables.split("&&").join("&"); // removing extra amphersands
var params:Array = textVariables.split('&');
for(var i:int=0, index=-1; i < params.length; i++)
{
var keyValuePair:String = params[i];
if((index = keyValuePair.indexOf("=")) > 0)
{
var key:String = keyValuePair.substring(0,index);
var value:String = keyValuePair.substring(index+1);
objectVariables[key] = value;
trace("[", key ,"] = ", value);
}
}
}
I wrote that code directly here, I don't have any AS3 editor here, so, maybe you'll find errors.
If you have data in String and it has a structure just like you wrote, you can do a workaround:
dataInString = dataInString.split("\n").join("").split("\r").join(""); // removing EOL
dataInString = dataInString.slice(0,-1); // removing last "&"
dataInString = dataInString.slice(0,1); // removing first "&"
var array:Array = dataInString.split("&&");
var myVariables:Object = new Object();
for each(var item:String in array) {
var pair:Array = item.split("=");
myVariables[pair[0]] = pair[1];
}
That should make you an object with proper variables.

Slickgrid - Column Definition with Complex Objects

I have a Java object where the person object contains a displayName object. I have converted it to a JSON object for my JSP. The data looks like the following:
var people = [
{"id":52959,"displayName":{"firstName":"Jim","lastName":"Doe","middleName":"A"},"projectId":50003,"grade":"8","statusCode":"A","gradYear":2016,"buyer":false},
{"id":98765,"displayName":{"firstName":"Jane","lastName":"Doe","middleName":"Z"},"projectId":50003,"grade":"8","statusCode":"A","gradYear":2016,"buyer":true}
];
I want to bind my columns to the name properties that reside within the displayName object, but I am cannot get the column definition to recognize where the data resides. Here is an example of my firstName column definition:
{id: 'displayName.firstName', field: 'displayName.firstName', name: 'First Name',
width: 110, sortable: true, editor: TextCellEditor, formatter: SpaceFormatter,
cssClass: '', maxLength: 250, editable: true}
The view does not render the names although the data is there. Is it possible to bind a column to an object property that resides within another object? If so, what am I doing wrong?
Slickgrid doesn't support this capability by default, but you can workaround it by adding custom value extractor to your options object:
var options = {
dataItemColumnValueExtractor: function(item, columnDef) {
var names = columnDef.field.split('.'),
val = item[names[0]];
for (var i = 1; i < names.length; i++) {
if (val && typeof val == 'object' && names[i] in val) {
val = val[names[i]];
} else {
val = '';
}
}
return val;
}
}
var grid = new Slick.Grid($("#slickgrid"), data, columns, options);
The code is tested with slickgrid 2.0 and is working just fine. Unfortunately seems that slickgrid code is a bit inconsistent and editors don't take into account this option, so this solution is usable only if you will display the data without editing.
I know this is a bit old... but my work around is to do a pre-process on my items. Basically, flattening the model out:
var preProcessItems = function (items) {
var newItems = [];
for (var i = 0; i < items.length; i++) {
var item = items[i];
item['firstName'] = item['displayName']['firstName'];
newItems[i] = item;
}
return newItems;
};
/// when the value is updated on the flat structure, you can edit your deep value here
var fNameFormatter = function (row, cell, value, columnDef, dataContext) {
// datacontext.displayName.firstName = value;
return value ? value : "";
};
This problem seems to be more a of a data modeling issue though.