JSON array in Node.js - javascript

I have been trying to figure this out for the past week and everything that i try just doesn't seem to work.
I have to create a web service on my local box that responds to requests. The client (that i did not write) will ask my service one question at a time, to which my server should respond with an appropriate answer.
So the last thing i have to do is:
When a POST request is made at location '/sort' with parameter 'theArray', sort the array removing all non-string values and return the resulting value as JSON.
theArray parameter will be a stringified JSON Array
From going through trail and error i have found out that the parameters supplied is:
{"theArray":"[[],\"d\",\"B\",{},\"b\",12,\"A\",\"c\"]"}
I have tried many different thing to try to get this to work. But the closest thing i can get is it only returning the same thing or nothing at all. This is the code that i am using to get those results:
case '/sort':
if (req.method == 'POST') {
res.writeHead(200,{
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
});
var fullArr = "";
req.on('data', function(chunk) {
fullArr += chunk;
});
req.on('end', function() {
var query = qs.parse(fullArr);
var strin = qs.stringify(query.theArray)
var jArr = JSON.parse(fullArr);
console.log(jArr); // Returns undefided:1
var par = query.theArray;
console.log(par); // returns [[],"d","B",{},"b",12,"A","c"]
function censor(key) {
if (typeof key == "string") {
return key;
}
return undefined;
}
var jsonString = JSON.stringify(par, censor);
console.log(jsonString); // returns ""
});
res.end();
};
break;
Just to clarify what I need it to return is ["d","B","b","A","c"]
So if someone can please help me with this and if possible responded with some written code that is kinda set up in a way that would already work with the way i have my code set up that would be great! Thanks

Edit: Try this:
var query = {"theArray":"[[],\"d\",\"B\",{},\"b\",12,\"A\",\"c\"]"};
var par = JSON.parse(query.theArray);
var stringArray = [];
for ( var i = 0; i < par.length; i++ ) {
if ( typeof par[i] == "string" ) {
stringArray.push(par[i]);
}
}
var jsonString = JSON.stringify( stringArray );
console.log(jsonString);
P.S. I didnt't pay attention. Your array was actually a string. Andrey, thanks for the tip.

The replacer parameter of JSON.stringify doesn't work quite like you're using it; check out the documentation on MDN.
You could use Array.prototype.filter to filter out the elements you don't want:
var arr = [[],"d","B",{},"b",12,"A","c"];
arr = arr.filter(function(v) { return typeof v == 'string'; });
arr // => ["d", "B", "b", "A", "c"]

edit: one-liner (try it in repl!)
JSON.stringify(JSON.parse(require('querystring').parse('theArray=%5B%5B%5D%2C"d"%2C"B"%2C%7B%7D%2C"b"%2C12%2C"A"%2C"c"%5D').theArray).filter(function(el) {return typeof(el) == 'string'}));
code to paste to your server:
case '/sort':
if (req.method == 'POST') {
buff = '';
req.on('data', function(chunk) { buff += chunk.toString() });
res.on('end', function() {
var inputJsonAsString = qs.parse(fullArr).theArray;
// fullArr is x-www-form-urlencoded string and NOT a valid json (thus undefined returned from JSON.parse)
var inputJson = JSON.parse(inputJsonAsString);
var stringsArr = inputJson.filter(function(el) {return typeof(el) == 'string'});
res.writeHead(200,{
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
});
res.end(JSON.stringify(stringsArr));
};
break;

Related

Creating & sending JSON from client to server, and expected result

I'm trying to parse user input from my webpage and store it in a JSON object using inline JavaScript, make a POST request to my Node.js server, and access the contents of the request.
In my example.html, I have a function which does the following:
var xhttp = new XMLHttpRequest();
dataToSubmit = [];
// find some inputs
for ( /* each row of input */ ) {
dataToSubmit.push({
'item': itemName,
'quantity': quantity,
'price': itemPrice
});
}
xhttp.open("POST", "http://localhost:8080/menu", true);
xhttp.setRequestHeader('Content-Type', 'application/json');
xhttp.send(JSON.stringify(dataToSubmit));
EDIT :
After the POST request, I have a dispatcher.js file that processes the requests:
function(request, response) {
var qs = require('querystring');
var requestBody = '';
request.on('data', function(data) { requestBody += data; });
request.on('end', function() {
var qs = require('querystring');
var passed_data = qs.parse(requestBody);
if(request.url === "/menu") {
var menu_handler = require("./menu.js");
menu_handler.processOrder(passed_data);
}
}
I'm exporting processOrder() from my menu.js. The issue is that on the server-side, I have to do the following in order to access the object:
processOrder: function(data) {
for (var a in data) { <-------------- Having to do this seems incorrect
// a is a string, inputs is the expected object
var inputs = JSON.parse(a);
}
}
My question is: is the way I'm creating the JSON object incorrect, or is the way I'm accessing it on the server-side incorrect? My expectation is that, on the server-side, I should be able to do something like this:
processOrder: function(data) {
var inputs = JSON.parse(data);
for (var input in inputs) {
// access to input.item, input.quantity, input.price
}
}
Make dataToSubmit an object:
dataToSubmit = {};
For each input row, add a uniquely keyed property to your dataToSubmit, and assign it an object:
dataToSubmit['keyName' + index] = {}
Assign this new object properties like:
dataToSubmit['keyName' + index]['item'] = itemName;
dataToSubmit['keyName' + index]['quantity'] = quantity;
dataToSubmit['keyName' + index]['price'] = itemPrice;
The cause of me not being able to access the dataToSubmit variable as a JSON object was that I was doing parsing at a previous layer before the data reached the processOrder function. The solution was to make the following changes in my dispatcher.js file (which processes the requestBody before it makes its eventual way to menu.js):
function(request, response) {
var qs = require('querystring');
var requestBody = '';
request.on('data', function(data) { requestBody += data; });
request.on('end', function() {
var qs = require('querystring');
var passed_data;
if(request.headers['content-type'] === 'application/json') { <--- parse JSON data
passed_data = JSON.parse(requestBody);
else {
passed_data = qs.parse(requestBody);
}
if(request.url === "/menu") {
var menu_handler = require("./menu.js");
menu_handler.processOrder(passed_data);
}
}
Furthermore, when creating the JSON object, the following needed to be done in order to access the data as a JSON object rather than as an array:
dataToSubmit = {'content': []};
dataToSubmit['content'].push(
{
'item': itemName,
'quantity': quantity,
'price': itemPrice
}
);

Securing JSON response through ajax in javascript (for(;;);)

I've been reading and I know there are similar questions, but I found no answer of what I'm looking for.
So it's about, for(;;); while(1); before the json string is outputted by an Ajax response.
Now what I wonder is how will this work? I'd like to try to use the same technique as many famous sites does like Facebook with for(;;);
So in the ajax.php file this is what I think has to be done:
ajax.php
$arr = array("value" => "something", "moreValues" => "moreSomething");
die("for(;;);".json_encode($arr));
Now the respone would be:
for(;;);{"value":"something","moreValues":"moreSomething"}
What shall I do with this string now? shall i remove for(;;); with a substr or something and then use JSON.parse(string); (Then why did I even send the for(;;); in the response if i'm going to remove it directly..?
And how will this help me with security issues, and how will a "user" enter the infinity loop for(;;); if something is wrong?
I know I am missing something, and I haven't found any example which demonstrates how to perform this. Anyone? And please if you find this question as a duplicate, please refer to an example where it's demonstrated in CODE not in words. Thanks!
I solved this with some simple Javascript, that might be used like this:
$.ajax({
url: mylink',
type: 'post',
complete: function(){
self.removeAttr('disabled');
removeLoading();
},
success: function(data){
s1 = new handleData(data);
if(s1.getError()){
return setMsgPopup(s1.getError(),1);
}
arr = s1.getResult();
}
});
Here is the handleData class:
var handleData = (function(){
var result=false;
var error=false;
var objSize=0;
var handleData = function(data){
fixedData = data;
arr = data.split('for (;;);');
if(!arr[1]){
this.result = false;
}else{
fixedData = arr[1];
}
try{
this.result = JSON.parse(fixedData);
}catch(e){
this.result = false;
}
if(this.result){
if(this.result['t'] == undefined){
if(this.result['error'] != undefined)
this.setError(this.result['msg']);
else
this.setError("An error have occured.");
}
if(this.result['error'] != undefined)
this.setError(this.result['msg']);
if(this.result['t'])
delete this.result['t'];
}else
this.setError("An error have occured.");
this.setSize();
};
handleData.prototype.setError = function(msgError){
this.error = msgError;
};
handleData.prototype.getError = function(){
return this.error;
};
handleData.prototype.getResult = function(){
return this.result;
};
handleData.prototype.setSize = function(){
if(!this.result)
return;
var size =0;
for(key in this.result) {
if(this.result.hasOwnProperty(key))
size++;
}
this.objSize = size;
}
handleData.prototype.getSize = function(){
return this.objSize;
};
return handleData;
})();
Notice this code is old as the question itself. It could be done better, but this is how I fixed it that time.

sorting a JSON in Node.js

I have been looking for a couple of days for the answer for this and nothing seems to work. Im kinda new to node.js and I'm working on only the server side to answer POST from the client side. This is kinda like an assignment that i have to do. What i need to do is when the client script, that i did not write, makes a POST request at location '/sort' with parameter theArray, i need to sort the array removing all non-string values and return the resulting value as JSON. The client script will send theArray parameter in a stringified JSON Array. So something like this
{"theArray":"[[],\"d\",\"B\",{},\"b\",12,\"A\",\"c\"]"}.
I have tried this code here:
case '/sort':
if (req.method == 'POST') {
res.writeHead(200,{
'Content-Type': 'application/json'
});
var fullArr = "";
req.on('data', function(chunk) {
fullArr += chunk;
});
req.on('end', function() {
var jPar = JSON.parse(fullArr);
var arr = "";
var par = jPar.theArray;
arr += par;
function censor(key, value) {
if (typeof value == "string") {
return value;
}
return undefined;
}
var jsonString = JSON.stringify(par, censor);
console.log(jsonString);
});
res.end();
};
break;
but it returns this with an error:
undefined:1
%2C%22A%22C%22
^
SyntaxError: Unexpected token h
at Object.parse (native) ...
Can someone please help me and if you can show me some code to help. Thanks
you need to decode POST data according to transport encoding (I believe it's application/x-www-form-urlencoded in your case)
var json = require('querystring').parse(fullArr).formParamName;
replace formParamName with actual name used in your POST form. Here is querystring module documentation
function parseBody (req, callback) {
var buffer = '';
req.on('data', function(chunk) {
buffer += chunk;
});
req.on('end', function() {
try {
callback(null, JSON.parse(buffer));
} catch(e) {
callback(e);
}
});
}
function stringFilter(element) {
return typeof element === 'string';
}
function requestHandler (req, res) {
parseBody(req, function(err, body) {
if(err) {
res.writeHead(400, {
'Content-Type': 'application/json'
});
return res.end(err.toString());
}
res.writeHead(200,{
'Content-Type': 'application/json'
});
var result = body.theArray.filter(stringFilter).sort();
res.end(JSON.stringify(result));
});
}
require('http').createServer(requestHandler).listen(3000);
I have left out the url handling, this is just for parsing the body, filtering out non-strings and I also added the sort().
You can test this with (if you name the file app.js):
node app.js
curl -H "Content-Type: application/json" -d '{"theArray": [[], "a", {}, "c", "B"]}' localhost:3000
Edit: This requires the input (request body) be valid JSON, though. If it looks like the data in the question then you would have to write a parser for that format. To me, it looks like somebody had an array such that
var arr = [[],"d","B",{},"b",12,"A","c"];
And then did
JSON.stringify({theArray: JSON.stringify(arr)});

Responding with a JSON object in Node.js (converting object/array to JSON string)

I'm a newb to back-end code and I'm trying to create a function that will respond to me a JSON string. I currently have this from an example
function random(response) {
console.log("Request handler 'random was called.");
response.writeHead(200, {"Content-Type": "text/html"});
response.write("random numbers that should come in the form of json");
response.end();
}
This basically just prints the string "random numbers that should come in the form of JSON". What I want this to do is respond with a JSON string of whatever numbers. Do I need to put a different content-type? should this function pass that value to another one say on the client side?
Thanks for your help!
Using res.json with Express:
function random(response) {
console.log("response.json sets the appropriate header and performs JSON.stringify");
response.json({
anObject: { item1: "item1val", item2: "item2val" },
anArray: ["item1", "item2"],
another: "item"
});
}
Alternatively:
function random(response) {
console.log("Request handler random was called.");
response.writeHead(200, {"Content-Type": "application/json"});
var otherArray = ["item1", "item2"];
var otherObject = { item1: "item1val", item2: "item2val" };
var json = JSON.stringify({
anObject: otherObject,
anArray: otherArray,
another: "item"
});
response.end(json);
}
var objToJson = { };
objToJson.response = response;
response.write(JSON.stringify(objToJson));
If you alert(JSON.stringify(objToJson)) you will get {"response":"value"}
You have to use the JSON.stringify() function included with the V8 engine that node uses.
var objToJson = { ... };
response.write(JSON.stringify(objToJson));
Edit: As far as I know, IANA has officially registered a MIME type for JSON as application/json in RFC4627. It is also is listed in the Internet Media Type list here.
Per JamieL's answer to another post:
Since Express.js 3x the response object has a json() method which sets
all the headers correctly for you.
Example:
res.json({"foo": "bar"});
in express there may be application-scoped JSON formatters.
after looking at express\lib\response.js, I'm using this routine:
function writeJsonPToRes(app, req, res, obj) {
var replacer = app.get('json replacer');
var spaces = app.get('json spaces');
res.set('Content-Type', 'application/json');
var partOfResponse = JSON.stringify(obj, replacer, spaces)
.replace(/\u2028/g, '\\u2028')
.replace(/\u2029/g, '\\u2029');
var callback = req.query[app.get('jsonp callback name')];
if (callback) {
if (Array.isArray(callback)) callback = callback[0];
res.set('Content-Type', 'text/javascript');
var cb = callback.replace(/[^\[\]\w$.]/g, '');
partOfResponse = 'typeof ' + cb + ' === \'function\' && ' + cb + '(' + partOfResponse + ');\n';
}
res.write(partOfResponse);
}
const http = require('http');
const url = require('url');
http.createServer((req,res)=>{
const parseObj = url.parse(req.url,true);
const users = [{id:1,name:'soura'},{id:2,name:'soumya'}]
if(parseObj.pathname == '/user-details' && req.method == "GET") {
let Id = parseObj.query.id;
let user_details = {};
users.forEach((data,index)=>{
if(data.id == Id){
user_details = data;
}
})
res.writeHead(200,{'x-auth-token':'Auth Token'})
res.write(JSON.stringify(user_details)) // Json to String Convert
res.end();
}
}).listen(8000);
I have used the above code in my existing project.
The JSON.stringify() method converts a JavaScript object or value to a JSON string, optionally replacing values if a replacer function is specified or optionally including only the specified properties if a replacer array is specified.
response.write(JSON.stringify({ x: 5, y: 6 }));
know more

jQuery: get the type of an Ajax response

I need to make an Ajax request, but its response may vary and it's decided on the server side.
Is there any way to know what type the response is?
It may look similar to:
$.post(url, pars, function (response, type) {
if (type=='json') ...
if (type=='html') ...
});
There's no built-in way to do this, it's determined and tossed away by jQuery.httpData (note: it will be jquery.ajax.httpData in 1.4.3).
Though you can take a look at the httpData source and run the same functions yourself, that's a bit wasteful, since jQuery's doing it already. I
If your choices are only json or html, you could check typeof response, it should be "string" for HTML, otherwise you have JSON, which you could also check and be sure about as well, for example: type && type.propertyAlwaysThere.
If you have control of the server-side code as well, the easiest thing will probably be to include a parameter with a value to specify the format.
Here's an example where I did the same type of thing you're describing. I loaded a table with customer values from data returned in xml, json, or string format, all driven by the value my server-side code returned as the format parameter:
function checkCusts(id, format, resultRegion) {
var address = "cust-lookup.jsp";
var data = "cust_id_list=" + getValue(id) + "&format=" + format;
if (address != "") {
ajaxPost(address, data,
function(request) {
parseCustomers(request, format, resultRegion);
});
}
}
function parseCustomers(request, format, resultRegion) {
if ((request.readyState == 4) && (request.status == 200)) {
var headings = new Array("Customer ID", "First Name", "Last Name", "Balance");
var rows = null, customers = null;
if ("xml" == format) {
var xmlDocument = request.responseXML;
customers = xmlDocument.getElementsByTagName("customer");
rows = new Array(customers.length);
var subElementNames = ["cust_id", "first_name", "last_name", "balance"];
for (var i=0; i<customers.length; i++) {
rows[i] = getElementValues(customers[i], subElementNames);
}
} else if ("json" == format) {
var rawData = request.responseText;
var data = eval("(" + rawData + ")");
rows = data.customers;
} else if ("string" == format) {
var rawData = request.responseText;
var rowStrings = rawData.split(/[\n\r]+/);
rows = new Array(rowStrings.length -1);
for (var i=1; i<rowStrings.length; i++) {
rows[i-1] = rowStrings[i].split("#");
}
}
var table = getTable(headings, rows);
htmlInsert(resultRegion, table);
}
}

Categories