Pretty printing JSON to a file in Node - json

So I have a very large JSON data which I am sending to a node server via AngularJS. This is the procedure I'm using to send data :-
var send_data="data="+encodeURIComponent(JSON.stringify($scope.records,null,4));
$http({
method : 'POST',
url : 'http://localhost:8888/updateDetails',
data : send_data,
responseType : "json",
headers: {
"Content-Type": 'application/x-www-form-urlencoded'
}
}).success(function(data, status, headers, config){
console.log(data);
});
I successfully managed to send a pretty printed JSON to the Node Server via the above code. However when I write this to a file using :-
jsonfile.writeFile(file, JSON.parse(req['body']['data']), function (err) {
console.error(err);
});
After some testing I figured out that the error is in the JSON.parse statement. Any way to pretty print JSON to a file?

Use JSON.stringify(data[, replacer[, indent]]):
jsonfile.writeFile(file, JSON.stringify(JSON.parse(req.body.data), 0, 4), function (err) {
console.error(err);
});
You also may or may not need to parse the response body though -- I believe responseType: "json" in the builder will automatically parse it for you:
jsonfile.writeFile(file, JSON.stringify(req.body.data, 0, 4), function (err) {
console.error(err);
});
Here's a complete working isolated example of how it works:
var fs = require('fs');
var req = JSON.parse('{"body": {"data": "Some text."}}');
fs.writeFile('test.json', JSON.stringify(req.body, 0, 4), function (err) {
});
Assuming you're handling POST requests via an HTTP listener or framework like express? Are you using a body parser to parse the incoming JSON?
Let's try:
console.log(req.body) to make sure your server recognizes the request.
Is it a JSON string? Is it valid? Or is it a javascript object (i.e. already been parsed)?
If it's been parsed, then my second suggestion will work. If it hasn't been parsed, parse it as I did in the first example.

Related

node request module: parsing XML as JSON

Until recently I've been fetching XML data using the node request module, and then running that XML through an XML to JSON converter. I discovered by accident that if I set json: true as an option (even knowing the endpoint returns XML, not JSON), I was actually getting back JSON:
var request = require('request');
var options = { gzip: true, json: true, headers: { 'User-Agent': 'stackoverflow question (https://stackoverflow.com/q/52609246/4070848)' } };
options.uri = 'https://api.met.no/weatherapi/locationforecast/1.9/?lat=40.597&lon=-74.26';
request(options, function (error, response, body) {
console.log(`body for ${options.uri}: ${JSON.stringify(body)}`);
});
The above call returns JSON, whereas the raw URL is actually sending XML. Sure enough, with json: false the returned data is XML:
var request = require('request');
var options = { gzip: true, json: true, headers: { 'User-Agent': 'stackoverflow question (https://stackoverflow.com/q/52609246/4070848)' } };
options.uri = 'https://api.met.no/weatherapi/locationforecast/1.9/?lat=40.597&lon=-74.26';
options.json = false; // <<--- the only difference in the request
request(options, function (error, response, body) {
console.log(`body for ${options.uri}: ${body}`);
});
So I thought "that's handy", until I tried the same trick with a different URL that also returns XML, and in this case the returned data is still XML despite using the same request options:
var request = require('request');
var options = { gzip: true, json: true, headers: { 'User-Agent': 'stackoverflow question (https://stackoverflow.com/q/52609246/4070848)' } };
options.uri = 'https://graphical.weather.gov/xml/SOAP_server/ndfdXMLclient.php?whichClient=NDFDgen&lat=40.597&lon=-74.26&product=time-series&temp=tempSubmit=Submit';
request(options, function (error, response, body) {
console.log(`body for ${options.uri}: ${body}`);
});
What is the difference here? How do I get the latter request to return the data in JSON format (so that I can avoid the step of converting XML to JSON myself)? Maybe the endpoint in the first example can detect that JSON is requested and it does in fact return JSON rather than XML?
EDIT weirdly, the first request is now returning XML rather than JSON even with json: true. So maybe this behaviour was down to what was being sent from the endpoint, and they've changed this even since I posted a few hours ago
So now that the behavior is unrepeatable, the answer is less useful for your particular problem, but I think it's worth pointing out that when you set json:true on the request module, it does a few things under the hood for you:
Sets the Accept header to 'application/json'
Parses the response body using JSON.parse()
Request types with a body also get the body automatically serialized as JSON
Request types with a body also get the Content-Type header added as 'application/json'
So perhaps they did change it, but there are plenty of web services I've seen that will detect the content-type to send based on the Accept header and respond appropriately for some set of types that make sense (usually XML or JSON, but sometimes CSV, TXT, HTML, etc).
To handle XML query, I usually do something like this using the request module:
import parser from "xml2json";
const resp = await rp({
method: "POST",
url: 'some url',
form: {xml_query}, // set XML query to xml_query field
});
const parsedData = parser.toJson(resp, {
object: true, // returns a Javascript object instead of a JSON string
coerce: true, // makes type coercion.
});

AJAX HTTP-POST-Request - Saving JSON responses

I want to make a HTTP-POST-Request with AJAX to call a JSON API. So, the API should return a response in JSON. I can see on the console of the API, that the request is successful. But the problem is, that no data or status is returned, or that I can't use it with JQuery. Here is my function:
$.post("http://api-adress/controller",
{
email: input_mail,
password: input_pw
},
function(data, status){
alert(data);
alert(status);
}, 'json');
I guess the problem is that the response from the Server does not get saved in the variables data and status correctly.
I would suggest to change a little bit your code like below:
var dataString = {
email: input_mail,
password: input_pw
}
$.post("http://api-adress/controller", dataString, function (result) {
})
.done(function (result) {
//Here is your result. You must parseJSON if it is json format
var data = jQuery.parseJSON(result);
})
.fail(function () {
//use this if you need it
})
Also make sure that you get the response through firebug in console tab. You can check there what you post, what you get etc.

Sending larger JSON strings via HTTP using Node

I am working on sending JSON data from my HTTP server to my client. I have been successful in sending smaller sized JSON responses to the client, but once I have to wait and collect all the data before sending, my code does not function properly. I am using the .on('data', function (){}) method to collect the data and build it back up and the .on('end', function(){}) to try sending the data, but my code never enters either of these methods.
My code for sending the larger sized JSON data is below:
exports.sendJson = function (req, resp, data) {
resp.writeHead(200, "Valid EndPoints", { "Content-Type": "application/json" });
var payload = '';
resp.on('data', function(data){
payload += data;
})
.on('end', function(){
resp.write(JSON.stringify(payload));
});
resp.end();
};
My code that works fine for smaller sized JSON data is as follows:
exports.sendJson = function (req, resp, data) {
resp.writeHead(200, { "Content-Type": "application/json" });
if(data) {
resp.write(JSON.stringify(data));
}
resp.end();
};
Thanks in advance. I'm actually pretty happy I got this far.
A HTTP server response is a Writable; it does not emit data events.
If the thing you pass in to sendJson's data parameter is an object, you just do exactly what you're doing in the second example. There is no need to buffer anything. (If the thing you pass to sendJson is a stream, just pipe it to the response.)
(When parsing received JSON, you must buffer the data you get from a Readable -- the HTTP response on the client.)

Angular $http service - force not parsing response to JSON

I have a "test.ini" file in my server, contain the following text:
"[ALL_OFF]
[ALL_ON]
"
I'm trying to get this file content via $http service, here is part of my function:
var params = { url: 'test.ini'};
$http(params).then(
function (APIResponse)
{
deferred.resolve(APIResponse.data);
},
function (APIResponse)
{
deferred.reject(APIResponse);
});
This operation got an Angular exception (SyntaxError: Unexpected token A).
I opened the Angular framework file, and I found the exeption:
Because the text file content start with "[" and end with "]", Angular "think" that is a JSON file.
Here is the Angular code (line 7474 in 1.2.23 version):
var defaults = this.defaults = {
// transform incoming response data
transformResponse: [function(data) {
if (isString(data)) {
// strip json vulnerability protection prefix
data = data.replace(PROTECTION_PREFIX, '');
if (JSON_START.test(data) && JSON_END.test(data))
data = fromJson(data);
}
return data;
}],
My question:
How can I force angular to not make this check (if (JSON_START.test(data) && JSON_END.test(data))) and not parse the text response to JSON?
You can override the defaults by this:
$http({
url: '...',
method: 'GET',
transformResponse: [function (data) {
// Do whatever you want!
return data;
}]
});
The function above replaces the default function you have posted for this HTTP request.
Or read this where they wrote "Overriding the Default Transformations Per Request".
You can also force angular to treat the response as plain text and not JSON:
$http({
url: '...',
method: 'GET',
responseType: 'text'
});
This will make sure that Angular doesn't try to auto detect the content type.

JSON nested object post to node.js server?

I want to POST an Object via JSON to node.js server.
The Object structure is nested, and never succeeded to receive and parse correctly on node.js server site.
EDIT2
I found a solution: see the answer section...
EDIT
I found
console.log(body);
itself output
val1=hello&val2%5Bval3%5D=world
//= {"val1":"hello","val2[val3]":"world"}
weired JSON way
client.js
var data ={val1:"hello",val2:{val3:"world"}};
console.log(data); // -> *1
$.ajax({
url:"/",
type:"POST",
dataType: 'json',
data:data,
success:function (res)
{
resHandler(res);
}
});
*1 ChromeDevelopersTool
Object
val1: "hello"
val2: Object
val3: "world"
server.js
var onreq = function (req, res)
{
if(req.method == 'POST')
{
var body = '';
req.on('data', function (data)
{
body += data;
});
req.on('end', function ()
{
var json = qs.parse(body);
console.log(json.val1); //hello
console.log(json.val2); //undefined
console.log(json.val3); //undefined
console.log(JSON.stringify(json));
//{"val1":"hello","val2[val3]":"world"}
});
}
I understand
val2[val3]
is
val2.val3
However,
Problem 1
JSON.stringify prints out
{"val1":"hello","val2[val3]":"world"}
not
{val1:"hello",val2:{val3:"world"}}
It's ugly, and I don't know why it's like that.
Problem 2
I can never get {val3:"world"}
console.log(json.val3); //undefined
Anyone can explain, and how can I POST a nested JSON to node.js server?
Thanks.
Do NOT use JSON typed data on jQuery Ajax, instead use Stringified JSON
I created a WIKI
http://code.google.com/p/kenokabe/wiki/nestedJSONproblem