Add value to array in JSON file with createWriteStream node - javascript

I have a problem writing a json file using creatwritestream NodeJS. The JSON in file is ok But it append in the file, I need overwrite the content. I storing selected answer when clicked on button.
Example:
Question A :
Evaluated selected : D ANSWER (Save this in json)
Question B:
Evaluated selected : C ANSWER (Save this in json)
I GOT:
{"IdTest":"1021","answers":[{"questionID":"1","answerSelected":"D"}]}\n {"IdTest":"1021","answers":[{"questionID":"1","answerSelected":"D"},{"questionID":"2","answerSelected":"C"}]}
json file image
This is my code:
//init variables
let jsonObject = {};
const JSON_ANSWERS_FILE = fs.createWriteStream("path/to/jsons/file.json", {
flags: 'w',
encoding: 'utf8'
});
//I created the key and value for the json object
jsonObject = {
"id": 123,
"answers": []
}
// BUTTON TO SAVE ANSWER IN JSON
jsonObject.answers.push({
"qID": $("#element").text(),
"selected": $("input:radio[name=radioName]:checked").attr("value")
})
JSON_ANSWERS_FILE.write(JSON.stringify(jsonObject), (error) => {
if (error) {
Swal.fire({
icon: 'error',
title: 'Oops...',
text: 'message'
})
}
})

Related

How to store objects in a Json file

I would like to store accounts in a json file.
Something like : accounts{[user: user1, email: email1], [user: user2. email: email2]}
Javascript file
Accounts = {
Nickname: form.getElementsByTagName('input')[0].value,
Email: form.getElementsByTagName('input')[3].value
};
var json = JSON.stringify(Accounts);
fs.appendFile('Accounts.json', json, function(err){});
When I add a second user this code make a new object and it looks like.
Json file
{"NickName": "user1", "Email": "Email1"}{"NickName": "user2", "Email": "Email2"}
Then, when I try to read the file and parse it I receive an unexpected error {
I think the Json file should look like
{
{"Name":"value"},
{"Name2":"value2"}
}
I fix the issue.
Here the solution with a mix of Michael Brune's solution.
// Read accounts.json
const Accounts = fs.readFileSync('Accounts.json', 'utf-8');
// Check if json file is empty
if(Accounts.length !== 0){
var ParsedAccounts = JSON.parse(Accounts);
}
else{
ParsedAccounts = [];
}
ParsedAccounts.push(Account);
const NewData = JSON.stringify(ParsedAccounts, null, 4);
// Write new data to accounts.json
fs.writeFileSync('Accounts.json', NewData);
Basically, I push the new data in ParsedAccounts then I write it in the json file.
Maybe there is another way, but if your file is pretty small, then try like this:
Accounts.json:
{
"other": "other data"
}
index.js
const fileData = fs.readFileSync('Accounts.json');
let parsedFileData
try {
parsedFileData = JSON.parse(fileData);
} catch (error) {
if (error instanceof SyntaxError) {
// Create empty object to append to since parse was not a success
parsedFileData = {};
// Create backup of old, possible corrupt file
fs.writeFileSync('Accounts.backup.json', fileData);
}
}
const newFileData = JSON.stringify({
...parsedFileData,
...newDataToAppend,
}, null, 4);
fs.writeFileSync('Accounts.json', newFileData);
First you can parse the file.
Assign new and old data to a object.
Then convert that to srting JSON.Stringify
The null and 4 are to write a nice pretty file
Then write it to the file directly.

Array.includes not working as expected with html file upload and localforage

So basically I'm making a website which allows the user to upload a .txt file and returns it for downloading it after encrypting it using a shift cipher.
I have the following HTML code
<div class="file-inp mainscreen-row-element level-2 enc">
Upload Text File
</div>
<input type="file" accept=".txt" id="inp-elem" hidden />
And I am storing some data in indexedDB if it isn't already there
localforage.getItem("encrypton-caesar-cipher").then(d => {
if (d == null) {
localforage.setItem("encrypton-caesar-cipher", {
enc: { inp: { text: [], files: [] }, out: { text: [], files: [] } },
dec: { inp: { text: [], files: [] }, out: { text: [], files: [] } },
ai: { inp: { text: [], files: [] }, out: { text: [], files: [] } }
});
}
});
And i my javascript includes this code
$(".file-inp").on("click", e => {
$("#inp-elem").trigger("click");
$("#inp-elem").on("change", () => {
const f = $("#inp-elem").prop("files");
localforage.getItem("encrypton-caesar-cipher").then(d => {
if (!(d.enc.inp.files.includes(f))) {
d.enc.inp.files.push(f);
localforage.setItem("encrypton-caesar-cipher", d);
}
});
});
});
So as the user uploads a file, i store the object in indexedDB with the help of localForage, and I have this conditional
if (!(d.enc.inp.files.includes(f)))
because i want to make sure I'm not storing the same object repeatedly
Now if I upload a file a.txt and go to the Dev Tools it is shown there, and if upload it again, my indexedDB data does not change, which is what I expect, but when I refresh the page, and then upload a.txt again, the same object is stored and shown in the Dev Tools twice, and this continues to increase if I reload the page and upload the same file.
I want to know what I'm doing wrong or is there a possible workaround?
The problem is that two javascript objects with the same content are not considered equal:
const object1 = {foo: 'bar'};
const object2 = {foo: 'bar'};
object1 == object2 // false
// but
object1 == object1 // true
But this works for primitives like string:
const string1 = 'foo';
const string2 = 'foo';
string1 == string2 // true
Maybe what you want is to use $("#inp-elem").val() which represents the path to the selected file and not the file itself. You can also calculate file contents hash if path is not what you want.

How to parse through a json array?

By using node js I generate the array below(2) , by parsing through multiple json files for a particular value.
My json files contains a list of IDs with their status : isAvailable or undefined.
So In my code i parse through all my json files but looking only for the first ID and get the statuts of Availability in the picture bellow. When it's true t means that the ID is available. As you can see the name of the file, it's the date and the hour the json was produced.
So What I want to achieve is write a function or anything simple, where i go through the array you can see in the picture.
Example:
We can see that the status is available for the first file, I wanna recover first file name with status available
("{ fileName: '2017-03-17T11:39:36+01:00',
Status: Available }"
when the status stop being available, in our example that would be here ( { fileName: '2017-04-06T11:19:17+02:00', contents: undefined } )
get:
{ fileName: '2017-04-06T11:19:17+02:00', Status: unavailable }
(2)
So here is part of my code where I generate this array :
Promise.mapSeries(filenames, function(fileName) {
var contents = fs
.readFileAsync("./availibility/" + fileName, "utf8")
.catch(function ignore() {});
return Promise.join(contents, function(contents) {
return {
fileName,
contents
};
});
}).each(function(eachfile) {
if(eachfile.contents){
jsonobject = JSON.parse(eachfile.contents);
if(jsonobject && jsonobject.hasOwnProperty('messages'))
// console.log(jsonobject.messages[0].message.results[2]);
eachfile.contents = jsonobject.messages[0].message.results[1].isAvailable;
}
eachfile.fileName = eachfile.fileName.substring('revision_'.length,(eachfile.fileName.length-5));
console.log(eachfile);
})
May someone help me please
Thank you,
Suppose you have an array:
[
{
filename : "2017-03-23 00:00:00",
contents : true
},
...
{
filename : "2017-03-23 00:00:00",
contents : undefined
},
{
filename : "2017-03-23 00:00:00",
contents : undefined
},
{
filename : "2017-03-23 00:00:00",
contents : true
}
]
where the ... represents a long stream of objects where the contents value is true.
You want to end up with a list of objects without consequent objects with the same contents value, meaning the result would look like:
[
{
filename : "2017-03-23 00:00:00",
contents : true
},
{
filename : "2017-03-23 00:00:00",
contents : undefined
},
{
filename : "2017-03-23 00:00:00",
contents : true
}
]
Im going to use jQuery because this is a javascript framework I am familiar with, but you should be able to translate it with ease to whatever framework you're using.
function doit(dataArray) {
var resultList = [];
var currentContent = "";
$.each(dataArray, function(index, value) {
if(currentContent != value.content) {
resultList.push(value);
currentContent = value.content;
}
});
console.log(resultList);
}
Note that you need an array with the data that looks like the data in your picture, however, you print every row. You might need to add those rows into a new array, and then pass that array to this function.

Setting up a Todo List server

I'm fairly new to Javascript, Node.js and JSON. I'm supposed to build some sort of Todo list application, where the user sends his todo to a server. I've already created the HTML and Javascript to execute the basic operation without the server.
I'm using the following program/languages in order to complete my assignment:
Vagrant (various NPM modules)
VirtualBox
Javascript (jQuery)
Currently i'm trying to send the data via the following lines of code:
//Create (simplified) "task"
item["id"] = task.dataset.id;
item["taskname"] = task.dataset.taskname;
item = JSON.stringify(item);
//Send code
$.ajax({
url: '/addtodo',
type: 'post',
dataType: 'json',
success: function (data) {
console.log(data);
},
data: item
});
Where as on the receiving side, I try to receive the data using the following lines of code:
app.post("/addtodo", function (req, res) {
var newTodo = req.body;
fs.writeFile("Somefile.json", JSON.parse(newTodo), function(err) {
if(err) {
res.json({"message":"Storing data failed"});
} else {
res.json({"message":"Data stored successfully"});
}
});
});
My objective is to get something like this in "Somefile.json"
[{
"id" : 2,
"taskname" : "Example task 2",
},
{
"id" : 2,
"taskname" : "Example task 2",
},
]
For now I get either errors or it changes the Somefile.json into [object Object].
Anyone care to explain what I did wrong and how I should fix it
Edit:
If I do not use JSON.parse i get : [object Object]
If I use JSON.stringify I get {"{\"id\":\"6\",\"taskname\":\"1234\"}":""}
Instead of the
JSON.parse(newToDo);
Use
JSON.stringify(newToDo);
This function will convert the object into a string and will give you the desired output.

Writing text to File in Node.JS

I'm new to Node.js. I have a JSON object which looks like the following:
var results = [
{ key: 'Name 1', value: '1' },
{ key: 'Name 2', value: '25%' },
{ key: 'Name 3', value: 'some string' },
...
];
The above object may or may not have different values. Still, I need to get them into a format that looks exactly like the following:
{"Name 1":"1","Name 2":"25%","Name 3":"some string"}
In other words, I'm looping through each key/value pair in results and adding it to a single line. From my understanding this single line approach (with double quotes) is called "JSON Event" syntax. Regardless, I have to print my JSON object out in that way into a text file. If the text file exists, I need to append to it.
I do not know how to append to a text file in Node.js. How do I append to a text file in Node.js?
Thank you!
You can use JSON.stringify to convert a JavaScript object to JSON and fs.appendFile to append the JSON string to a file.
// write all the data to the file
var fs = require('fs');
var str = JSON.stringify(results);
fs.appendFile('file.json', str, function(err) {
if(err) {
console.log('there was an error: ', err);
return;
}
console.log('data was appended to file');
});
If you want to add just one item at a time, just do
// Just pick the first element
var fs = require('fs');
var str = JSON.stringify(results[0]);

Categories