How can I pretty-print JSON using node.js? - json

This seems like a solved problem but I am unable to find a solution for it.
Basically, I read a JSON file, change a key, and write back the new JSON to the same file. All works, but I loose the JSON formatting.So, instead of:
{
name:'test',
version:'1.0'
}
I get
{name:'test',version:'1.1'}
Is there a way in Node.js to write well formatted JSON to file ?

JSON.stringify's third parameter defines white-space insertion for pretty-printing. It can be a string or a number (number of spaces). Node can write to your filesystem with fs. Example:
var fs = require('fs');
fs.writeFile('test.json', JSON.stringify({ a:1, b:2, c:3 }, null, 4));
/* test.json:
{
"a": 1,
"b": 2,
"c": 3,
}
*/
See the JSON.stringify() docs at MDN, Node fs docs

I think this might be useful... I love example code :)
var fs = require('fs');
var myData = {
name:'test',
version:'1.0'
}
var outputFilename = '/tmp/my.json';
fs.writeFile(outputFilename, JSON.stringify(myData, null, 4), function(err) {
if(err) {
console.log(err);
} else {
console.log("JSON saved to " + outputFilename);
}
});

If you just want to pretty print an object and not export it as valid JSON you can use console.dir().
It uses syntax-highlighting, smart indentation, removes quotes from keys and just makes the output as pretty as it gets.
const jsonString = `{"name":"John","color":"green",
"smoker":false,"id":7,"city":"Berlin"}`
const object = JSON.parse(jsonString)
console.dir(object, {depth: null, colors: true})
Under the hood it is a shortcut for console.log(util.inspect(…)).
The only difference is that it bypasses any custom inspect() function defined on an object.

If you don't want to store this anywhere, but just view the object for debugging purposes.
console.log(JSON.stringify(object, null, " "));
You can change the third parameter to adjust the indentation.

I know this is old question. But maybe this can help you 😀
JSON string
var jsonStr = '{ "bool": true, "number": 123, "string": "foo bar" }';
Pretty Print JSON
JSON.stringify(JSON.parse(jsonStr), null, 2);
Minify JSON
JSON.stringify(JSON.parse(jsonStr));

what about this?
console.table(object)

Another workaround would be to make use of prettier to format the JSON.
The example below is using 'json' parser but it could also use 'json5', see list of valid parsers.
const prettier = require("prettier");
console.log(prettier.format(JSON.stringify(object),{ semi: false, parser: "json" }));

if prettify is name value pairs on new lines then specifying number of spaces in stringify didn't work for me the only thing that worked for me was
await fs.promises.writeFile('testdataattr.json',JSON.stringify(datatofile, null,'\r\n'),'utf8') ;

Related

Angular 7 HTTP GET send JSON object as a parameter

Im trying to send a json structure to a rest service from angular doing something like this
let test5var = {
"test5var1": {
"test5var2": "0317",
"test5var3": "9556"
},
"test5var4": "123",
"test5var": "0000046"
}
let dataPrincipalBlnc = {"test": {"test1": {"test2": "0317","test3": {"IDIOMA_ISO": " en","DIALECTO_ISO": "US"},"channel": "INT"},"input": {"test5": test5var}}};
let headers = new HttpHeaders();
headers.append('Content-Type', 'application/json');
let params = new HttpParams().set("requestData", dataPrincipalBlnc.toString()).set("authenticationType", this.authType);
return this.http.get(this.url, {params: params});
The result of the request should look like follows:
https://example.com/test?authenticationType=cookie&requestData=%7B%test%22:%7B%22test1%22:%7B%22test2%22:%220317%22,%22test3%22:%7B%22IDIOMA_ISO%22:%22+en%22,%22DIALECTO_ISO%22:%22US%22%7D,%22channel%22:%22INT%22%7D,%22input%22:%7B%22test5%22:%7B%22test5var1%22:%7B%22test5var2%22:%220317%22,%22test5var3%22:%229556%22%7D,%22test5var4%22:%22123%22,%22test5var5%22:%220000986%22%7D%7D%7D%7D
But it is currently sent as:
https://example.com/test?requestData=%5Bobject%20Object%5D&authenticationType=cookie
Any ideas how can I send the json object to looks as the first request? Do I need to manually convert the json to a valid uri format?
In angularJS is working fine just using the following code:
var data = {
"test1": {
"test2": {
"test3": "0317",
"test4": {
"IDIOMA_ISO": " en",
"DIALECTO_ISO": "US"
},
"channel": "INT"
},
"input": {
"test5": test5var
}
}
};
$http.get(url, {
params: {
authenticationType: authType,
requestData: data
}
}).then(success(deferred), error(deferred));
I have also tried using the following code but the result is adding more characters and the backend is failling because it says the JSON is not in a valid format:
encodeURIComponent(JSON.stringify(dataPrincipalBlnc)
?requestData=%257B%2522test%2522%253A%257B%2522test1%2522%253A%257B%2522test2%2522%253A%25220317%2522%252C%2522test3%2522%253A%257B%2522IDIOMA_ISO%2522%253A%2522%2520en%2522%252C%2522DIALECTO_ISO%2522%253A%2522US%2522%257D%252C%2522channel%2522%253A%2522INT%2522%257D%252C%2522input%2522%253A%257B%2522test5%2522%253A%257B%2522test5var1%2522%253A%257B%2522test5var2%2522%253A%25220317%2522%252C%2522test5var4%2522%253A%25229556%2522%257D%252C%2522test5var4%2522%253A%2522123%2522%252C%2522test5var5%2522%253A%25220003303%2522%257D%257D%257D%257D&authenticationType=cookie
Thanks
Regards
Any JSON object being passed to the service should be sent via response body.
You should add valid string parameters only in the url.
Also there is url size limitation for most browsers, so bigger object may lead you to the long url problem.
You are seeing the requestData=%5Bobject%20Object%5D&authenticationType=cookie because it cannot put a JSON object in url query string.
Some characters cannot be part of a URL (for example, the space) and some other characters have a special meaning in a URL: for example, the character # can be used to further specify a subsection (or fragment) of a document; the character = is used to separate a name from a value. A query string may need to be converted to satisfy these constraints. This can be done using a schema known as URL encoding.
Use JSON.stringify when you have a JavaScript Object and you want to convert it to a string (containing a JSON text). This is called serialization.
Regardless to JSON:
Use encodeURIComponent whenever you want to send "problematic" characters in the URL such as &, % etc. The opposite is decodeURIComponent.
Still i would prefer to send the object in the request body.
So in your case use:
let params = new HttpParams()
.set("requestData", encodeURIComponent(JSON.stringify(dataPrincipalBlnc)))
.set("authenticationType", this.authType);
Adding to #nircraft answer (which is very elaborate and good) this implementation seems to does the trick for you,
let test5var = {
"test5var1": {
"test5var2": "0317",
"test5var3": "9556"
},
"test5var4": "123",
"test5var": "0000046"
}
let dataPrincipalBlnc = '{"test": {"test1": {"test2": "0317","test3": {"IDIOMA_ISO": " en","DIALECTO_ISO": "US"},"channel": "INT"},"input": {"test5": test5var}}}';
let headers = new HttpHeaders();
headers.append('Content-Type', 'application/json');
let params = new HttpParams().set("requestData", encodeURIComponent(dataPrincipalBlnc)).set("authenticationType", this.authType);
return this.http.get(this.url, {params: params});
In Javascript you can basically enclose a string in '' or "".
When you don't enclose the string specifically I believe it is enclosed with "", thus making your JSON response in need of escape characters when you use stringify.
Enclosing the string like this will make sure that the double quotes will make sure that it won't need escape characters.
Let me know if you have any questions.
I just fixed the issue by defining the data as an object and using just the JSON.stringify:
let dataPrincipalBlnc: object;
let dataPrincipalBlnc = {"test": {"test1": {"test2": "0317","test3": {"IDIOMA_ISO": " en","DIALECTO_ISO": "US"},"channel": "INT"},"input": {"test5": test5var}}};
let params = new HttpParams().set("requestData", JSON.stringify(dataPrincipalBlnc)).set("authenticationType", this.authType);
Thanks for your help
Regards

Microsoft Bot Framework using variables in Prompts.choice

My current code for asking a yes/no question is
builder.Prompts.choice(session, q15, "Yes|No", { listStyle: builder.ListStyle.button });
I want to store the strings "Yes" and "No" in a JSON file and access them by their variable names, instead of hardcoding it. How can I do that?
As the definition of choice():
choice(session: Session, prompt: TextOrMessageType, choices: string|Object|string[]|IChoice[], options?: IPromptChoiceOptions): void;
You can pass a string array as the choices. So please consider the following code snippet:
//assume you have read the json string from a file and use it as following
const json_string = `{
"VARIABLE_YES":"Yes",
"VARIABLE_NO":"No"
}`;
const json_obj = JSON.parse(json_string);
builder.Prompts.choice(session, 'Make a choice', [json_obj.VARIABLE_YES, json_obj.VARIABLE_NO], {
listStyle: builder.ListStyle.button
});

cordova readAsText returns json string that can't be parsed to JSON object

I read my json file using http and cordova file readAsText functions.
http request returns an object which is ok.
cordova file readAsText function return 'string' which contain extra "r\n\" symbols. This make it impossible to use JSON.parse(evt.target.result)
function readJson(absPath, success, failed){
window.resolveLocalFileSystemURL(absPath, function (entry) {
entry.file(function (file) {
var reader = new FileReader();
reader.onloadend = function (evt) {
success(evt.target.result);
};
reader.readAsText(file);
}, failed);
}, failed);
}
readJson(cordova.file.dataDirectory + 'my.json', function(res){
console.log(JSON.parse(res)); //here I've got an parsing error due to presence of r\n\ symbols
}, failed );
How to read JSON files using cordova?
UPDATE:
funny thing that the following works:
a = '{\r\n"a":"1",\r\n"b":"2"\r\n}';
b = JSON.parse(a);
so the problem not only with \r\n... there is something else that is added by cordova readAsText
UPDATE2
as a workaround I use now var object = eval("(" + res + ")")
Still search for a common way to load json objects...
No one has answered this and I just had to solve it for my project, so I will post my solution.
The readAsText method outputs a string, so you CAN actually run a replace on it, but what you need to do is use a RegExp to find the newline character. here's my solution:
var sanitizerRegex = new RegExp(String.fromCharCode(10), 'g');
var sanitizedData = JSON.parse(result.replace(sanitizerRegex, ''));
I've used the String method fromCharCode to get the specific newline character and the "g" flag to match all instances in the entire string. The problem with your string solution is that you can't do a string replace using the characters for backslash and "n" because the issue is the actual new line character, which is merely represented as "\n".
I do not know the reason JSON.parse can't handle the newline character, or why the file plugin introduces this problem, but this solution seems to work for me.
Also, NEVER use eval like this if you can avoid it, especially on input from a source like a JSON file. Even in a cordova app, using eval is potentially very unsafe.
I found out the solution after debug deeply. readAsText function returned text has one more letter at the first position of text.
Example:
{"name":"John"} => ?{"name":"John"} (?: API didn't return ?, just one string)
I confirmed this with length of result, so we need to use substr(1) before parse JSON.
fileContent = fileContent.substr(1);
var jData = jQuery.parseJSON(fileContent);

JSON.parse: expected property name or '}'

Data contains (/"/):
{"test":"101","mr":"103","bishop":"102"}
script:
console.log($.parseJSON(result));
I'm getting error,
JSON.parse: expected property name or '}'.
Had same issue when used single quotes in JSON file, changed to double quotes for all string properties/values and it's working OK now.
Change:
JSON.parse("{'wrongQuotes': 5}")
To:
JSON.parse('{"rightQuotes": 5}')
If you're receiving the JSON with the encoded ", you'll have to replace each instance of " with a true " before doing JSON.parse. Something like:
myJSONstring.replace(/"/ig,'"');
My case was even simpler.
Having confused JSON with plain JS, I didn't put the object keys in double quotes.
❌:
{
title: "Hello World!"
}
✅:
{
"title": "Hello World!"
}
The irony is, Postman even highlighted this to me, but I ignored. Sleep is the answer.
For anyone who is using laravel blade and declaring a JS variable in a view.
You need to use:
var json = JSON.parse('{!! $json !!}');
Otherwise you will get this error due to the quotes being parsed as "
Change
{"test":"101","mr":"103","bishop":"102"}
To
'{"test":"101","mr":"103","bishop":"102"}'
if this is coming from the server (PHP)
i.e <?php $php_var = ["test" => "101", "mr" => "103", "bishop" => "102"]?>
then on Javascript end
var javascript_var = $.parseJSON('<?= json_encode($php_var) ?>');
/* suppose your json are single quote, it's necessary replace it single quote before, a simple example*/
let ojson = "{'name':'peterson'}";
ojson = ojson.replace(/'/g, '"');
ojson = JSON.parse(ojson);
console.log(ojson['name'])
for example, if u get something like this
{ "location": "{'lat': 4.6351144, 'lng': -74.12011199999999}" }
from your server, or recently get a bad converted format.
first,get your string
myItemString = "{'lat': 4.6351144, 'lng': -74.12011199999999}"
and change the keys using replace, and later json.parse,
'key' to ---> "key"
const key1 = myItemString.replace("'lat'",'"lat"')
const key12 = key1.replace("'lng'", '"lng"');
const obj = JSON.parse(key12)
console.log(obj)
You can try using stringifying before parsing:
JSON.parse(JSON.stringify(result))

How to avoid quotes when encoding a JSON object

I need to create something like the following JSON entity:
{
"foo": function() { *some code* }
}
Can any of the common JSON libraries (json, jsonb, aeron etc.) easily achieve that?
I didn't find a way to tell the library not to quote the function part when encoding.
Thanks,
p.s. I understand the reason for not allowing such usage is to enforce correct syntax, but I'm willing to take that risk here.
That is not a JSON entity, but a JavaScript object. JSON has no concept of functions.
The only way to have a function encoded in JSON is indeed to encode it in a string:
{ "foo": "function() { return \"Hello, World\" }" }
When you want to execute that function in JavaScript, you'll have to eval the string:
var jsonObj = JSON.parse('{ "foo": "function() {return \\"Hello, World\\";}" }');
var jfoo = eval('(' + jsonObj.foo + ')');
alert(jfoo()); // Shows a dialog box "Hello, World"
Note that this allows the source of the JSON to execute arbitrary JavaScript in the context of your website or application. Therefore, you should transfer data instead of functions whenever possible, and make sure not to eval code from untrusted sources.