sorting a JSON in Node.js - javascript

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)});

Related

Sending data from NodeJS to the client by using Ajax calls

I increase a value at the server by running an Ajax call and want to update my UI after doing this
function increaseHitpoints(){
$.ajax({
type: 'GET',
url: 'http://localhost:8888/incHp/2312'
}).done(function (data) {
$("#txtHitpoints").html(data);
});
}
In my app.js I read a JSON file, manipulate the value, write it back to the file and return it to the client
app.get('/incHp/:id', function (req, res) {
var database = './database.json';
fs.readFile(database, 'utf8', function (err, data) { // read the data
var json = JSON.parse(data);
var users = json.users;
var hitpoints;
users.find(u => {
if (u.id === Number(req.params.id)) { // get the user by id
u.hitpoints++;
hitpoints = u.hitpoints;
}
});
json = JSON.stringify(json);
fs.writeFile(database, json, (err) => { // update the JSON file
// -> missing part here <-
});
});
});
what do I have to pass into the missing part if I want to return the new value? The new value would be hitpoints
I tried res.send(hitpoints); but it seems this function wants to return a status code, not a value.
If you send a numerical value, it will be observed as an HTTP response code
https://expressjs.com/en/api.html#res
But you can send your hitpoints as a string res.send(hitpoints.toString())or as json res.send({hits: hitpoints});
Depends on what format you want your response to be. I prefer using JSON. So in JSON case you would do this:
fs.writeFile(database, json, (err) => {
res.status(200).json({yourKey: yourValue});
});
Then you can access the JSON object in your frontend:
$("#txtHitpoints").html(data.yourKey);

Log images after successful http request using Node.js

I'm creating a script that will make a request 2 times per second to a localserver of cameras network and after it gets a positive response that camera detected someone I want to log three images.
In the json config file I have the triggerURL of the server, the interval port, the dataDir where logged images should be saved and a track array which contains the url of those images and the fileName they should receive.
This is the code of the script I use after reading the JSON file:
var configGet = {
host: config.triggerURL
, port: config.interval
, method: 'GET'
};
setInterval(function () {
var request = http.request(configGet, function (response) {
var content = "";
// Handle data chunks
response.on('data', function (chunk) {
content += chunk;
});
// Once we're done streaming the response, parse it as json.
response.on('end', function () {
var data = JSON.parse(response);
if (data.track.length > 0) {
//log images
var download = function (uri, filename, callback) {
request.head(uri, function (err, res, body) {
request(uri)
.pipe(fs.createWriteStream(filename))
.on('close', callback);
});
};
for (var image in data.track) {
var path = config.dataDir + '/' + image.fileName
download(image.url, path.format(config.timestamp), function () {
console.log('done');
});
}
}
});
// Report errors
request.on('error', function (error) {
console.log("Error while calling endpoint.", error);
});
request.end();
}, 500);
});
I have the following questions:
This method produces some kind of error with the download process of the images.Can you identify it?
Is there a better way of doing this process?
Without running the code or deeper inspection; should not "data = JSON.parse(response)" rather be "data = JSON.parse(content)"? Also, if data is undefined or does not contain "track" the "if (data.track.length > 0)" will throw an error. This can be fixed with "if (data && data.track && data.track.length > 0)".
I can not think of a very much better way. I would break it up more in functions to make the code more clear though.

Sails.js Sending json object returned in https.request to the view

Just learning Sails.js so go easy on me.
I have queried an XML service and successfully jsonified it using xml2js
var req = https.request(options, function(res) {
var xml = '';
res.on('data', function(chunk) {
xml += chunk;
});
res.on('end', function () {
var result = parseString(xml, function (err, result) {
console.log(JSON.stringify(result)); // Position 1
});
return result;
});
});
req.on('error', function(e) {
console.log('problem with request: ' + e.message);
});
req.write(data);
var result = req.end();
console.log('Result: ' + JSON.stringify(result)); // Position 2
res.view({ message : 'hello', result : result });
The view is loading fine, and <%= message %> outputs hello. Great.
Position1 console.log is returning the stringified json object - Great.
Position 2 consile.log is returning Result: true - Not good.
I need to be able to get that json data to my view for parsing. How do I do this?
It looks like you're assuming that calling req.end() will give you the response from the https.request you started above. There are a couple of things wrong with that:
req.end() is used to finish writing to an open request, not to get a response. According to the docs, the return value is unspecified.
The https.request call is asynchronous; even if req.end() worked like you want it to, the response wouldn't have come in by the time you call it.
The solution is to put your response code (i.e. your res.view) inside the handler for the end event that you've already written. I'd also recommend refactoring your code to use different variable names for the remote request / response so that they don't collide with the req and res variables in your controller action. The whole thing would then be something like:
myAction: function (req, res) {
// Not sure how you're setting options, so just an example
var options = {url: 'http://example.com', ...}
var request = https.request(options, function(response) {
var xml = '';
response.on('data', function(chunk) {
xml += chunk;
});
response.on('end', function () {
var result = parseString(xml, function (err, result) {
return res.view({ message : 'hello', result : JSON.stringify(result)});
});
});
});
request.on('error', function(e) {
console.log('problem with request: ' + e.message);
res.serverError(e);
});
}
You might also look into using something like the Request module to simplify your external request; it would save you from having to write event handlers for data and end.
if you want to pass json to some javascript variable:
var clientJsonVar = <%- JSON.stringify(serverSideJson)%>

JSON array in Node.js

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;

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

Categories