I need help replacing data inside of a JSON file using NODE.JS. My current method adds it with the same ID which is correct. However, when the data is received back, it drops the last duplicate because it found the old value first. I think what I really need to do is select JSON element by ID. Then replace it with the new.
Here is my AJAX request:
putComment: function(commentJSON, success, error) {
$.ajax({
type: 'post',
url: 'http://localhost:8080',
data: JSON.stringify(commentJSON),
success: function(comment) {
success(comment)
},
error: error
});
},
Here's my NODE:
if (req.method == 'POST') {
req.on('data', function(chunk) {
var element = JSON.parse(chunk);
fs.readFile("comments-data.json", 'utf8', function(err, json) {
var array = JSON.parse(json);
array.push(element);
fs.writeFile("comments-data.json", JSON.stringify(array), function(err) {
if (err) {
console.log(err);
return;
}
console.log("The file was saved!");
});
});
res.end('{"msg": "success"}');
});
};
Here is the data with duplicate id's:
[
{
"id": "c1",
"parent": null,
"created": "2016-08-12T19:57:21.282Z",
"modified": "2016-08-12T19:57:21.282Z",
"content": "test",
"fullname": "John Clark",
"profile_picture_url": "https://viima-app.s3.amazonaws.com/media/user_profiles/user-icon.png",
"created_by_current_user": true,
"upvote_count": 0,
"user_has_upvoted": false
},
{
"id": "c1",
"parent": null,
"created": "2016-08-12T19:57:21.282Z",
"modified": 1471031853696,
"content": "test 123",
"fullname": "John Clark",
"profile_picture_url": "https://viima-app.s3.amazonaws.com/media/user_profiles/user-icon.png",
"created_by_current_user": true,
"upvote_count": 0,
"user_has_upvoted": false
}
]
Are you just trying to replace the item if it exists? If so, you could do something like this:
var array = JSON.parse(json);
var isNew = true;
for (var i = 0; i < array.length; i++) {
if (array[i].id === element.id) {
array[i] = element;
isNew = false;
break;
}
}
//doesn't exist yet
if (isNew) {
array.push(element);
}
fs.writeFile("comments-data.json", JSON.stringify(array), function(err) {
if (err) {
console.log(err);
return;
}
console.log("The file was saved!");
});
Related
I want to read the values of key, access, path, bucket and bucketPath and use them in the JSON file test.json.
I have a function that reads the content of configuration.js and attempts to write to test.json. Currently, I am able to write the values of bucket.I get the changed/new values and lines of null for the rest of the json.
I want to always return the new values and the other objects in the file. Also, in cases where bucket already has a value, I want it replaced by whatever is read from configuration.json
How can I fix this, and how can i change the values for the rest access, key, path and bucketpath?
index.js
const fs = require("fs").promises;
async function readJSON(filePath, values) {
const data = await fs.readFile(filePath);
try {
return JSON.parse(data);
} catch (err) {
console.log(err);
}
}
(async() => {
const credentials = await readJSON("./configuration.json");
const path = credentials.path;
const bucket = credentials.bucket;
const access = credentials.access;
const key = credentials.key;
const bucketPath = credentials.bucketPath;
const data = await jsonReader("./test.json");
const finalJSON = data.data ? .map((x) => {
if (x.type == "s3 credentials") return { ...x, bucket };
});
await fs.writeFile(
"./test.json",
JSON.stringify({
data: finalJSON
})
);
})();
test.json
{
"label": "storage record",
"data": [{
"id": "8902uw",
"type": "config",
"values": {
"access": "$access",
"key": "$key"
}
},
{
"id": "893wh002jei",
"type": "s3 credentials",
"bucket": ""
},
{
"id": "90yueps",
"type": "upload",
"input": "localhost: `$path`"
},
{
"id": "9028901",
"type": "change",
"name": "Adjust data",
"measure": [{
"t": "setter"
},
{
"p": "filename",
"to": "$join([\"$bucketPath\", data])"
}
],
"fixed": ""
}
]
}
configuration.json
{
"key": "880082",
"access": "793082",
"path": "/store",
"bucket": "testBucket",
"bucketPath": "/record"
}
Currently, when I run this, I get:
{
null,
"data": [{
null,
null,
null,
null
{
"id": "893wh002jei",
"type": "s3 credentials",
"bucket": ""
},
{
null,
null,
null
]
}
might this be a solution !
const fs = require('fs');
const fileName = './file.json';
const file = require(fileName);
file.key = "new value";
fs.writeFile(fileName, JSON.stringify(file), function writeJSON(err) {
if (err) return console.log(err);
console.log(JSON.stringify(file));
console.log('writing to ' + fileName);
});
[Updated answer]
From what you comment:
it's the same question. So when I run what I have, I get null for the other objects. I want test.json to remain the same just with updated values.
const testObj = await jsonReader("./test.json");
const finalJSON = {
...testObj,
data: testObj.data?.map((x) => {
if (x.type === 's3 credentials') {
return { ...x, bucket };
} else {
return x;
}
})
}
// which the code I gave above,
// the `finalJSON` now is the clone of the original from `test.json`
// plus updated values
await fs.writeFile(
"./test.json",
JSON.stringify(finalJSON)
);
[Original answer]
There is a problem with the function you pass to the map function.
The condition if without else.
I think you need else { return x; } to return original data if x.type is not what you expected.
I have an API End point that i am trying to assign variables to, now the one JSON data is an array and I Loop over it to get the data out in my console log, the difficulty i am having is that i want to assign variables to them.
Here is my code:
const request = require('request');
request('https://fantasy.premierleague.com/api/leagues-classic/1114549/standings/?page_new_entries=1&page_standings=1&phase=1', { json: true }, (err, res, body) => {
if (err) { return console.log(err); }
var data = body.standings.results;
data.forEach(obj => {
Object.entries(obj).forEach(([key, value]) => {
console.log(`${key} ${value}`);
});
console.log('-------------------');
});
});
and here is my JSON data:
{
"league": {
"id": 1114549,
"name": "The crew",
"created": "2020-09-11T17:36:20.083556Z",
"closed": false,
"max_entries": null,
"league_type": "x",
"scoring": "c",
"admin_entry": 3523866,
"start_event": 1,
"code_privacy": "p",
"rank": null
},
"new_entries": {
"has_next": false,
"page": 1,
"results": []
},
"standings": {
"has_next": false,
"page": 1,
"results": [
{
"id": 30771462,
"event_total": 8,
"player_name": "Mohammed Ismail",
"rank": 1,
"last_rank": 0,
"rank_sort": 1,
"total": 8,
"entry": 3808290,
"entry_name": "Moe"
}
Now I am trying to console log only the standings.result.player_name in my console log so i can use it else where, how do i do that
So my output in the console should only be "player_name": "Mohammed Ismail",
I'm not sure that i get the question, but in case if you want to get all player_name and collect it in array as example, You can do it next:
const request = require('request');
const url = 'https://fantasy.premierleague.com/api/leagues-classic/1114549/standings/?page_new_entries=1&page_standings=1&phase=1';
async function getStandings(url) {
return new Promise((resolve, reject) => {
request(
url,
{ json: true },
(err, res, body) => {
if (err) {
reject(err);
return;
}
resolve(body.standings.results);
}
);
});
}
(async () => {
const data = await getStandings(url);
// here you will receive array of stadings
console.log('data : ', data);
})();
I have the following script that outputs a json formatted object:
function test() {
autoscaling.describeAutoScalingGroups(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(JSON.stringify(data)); // successful response
});
}
test();
This outputs the following json:
{
"ResponseMetadata": {
"RequestId": "##################"
},
"AutoScalingGroups": [
{
"AutoScalingGroupName": "################",
"AutoScalingGroupARN": "arn:aws:autoscaling:eu-west-1:#########:autoScalingGroup:###########",
"LaunchConfigurationName": "######-LC-###########",
"MinSize": 0,
"MaxSize": 0,
"DesiredCapacity": 0,
"DefaultCooldown": 300,
"AvailabilityZones": [
"eu-west-1b",
"eu-west-1c",
"eu-west-1a"
],
"LoadBalancerNames": [
"#########-ELB-###########"
],
"TargetGroupARNs": [
],
"HealthCheckType": "ELB",
"HealthCheckGracePeriod": 300,
"Instances": [
],
"CreatedTime": "2017-11-08T18:22:05.093Z",
"SuspendedProcesses": [
{
"ProcessName": "Terminate",
"SuspensionReason": "User suspended at 2017-11-08T18:22:14Z"
}
],
"VPCZoneIdentifier": "subnet-######,subnet-#######,subnet-#######",
"EnabledMetrics": [
],
"Tags": [
{
"ResourceId": "#######-ASG-##########",
"ResourceType": "auto-scaling-group",
"Key": "aws:cloudformation:logical-id",
"Value": "ASG",
"PropagateAtLaunch": true
},
{
"ResourceId": "#######-ASG-#########",
"ResourceType": "auto-scaling-group",
"Key": "aws:cloudformation:stack-id",
"Value": "arn:aws:cloudformation:eu-west-1:########:stack/##############",
"PropagateAtLaunch": true
},
{
"ResourceId": "################",
"ResourceType": "auto-scaling-group",
"Key": "aws:cloudformation:stack-name",
"Value": "#######",
"PropagateAtLaunch": true
}
],
"TerminationPolicies": [
"Default"
],
"NewInstancesProtectedFromScaleIn": false
}
]
}
I need to get the value of "SuspendedProcesses":[{"ProcessName": (see above)
Then if the value of "ProcessName" == "Terminate" (as it is above) do this else do this.
I know how to construct the if else syntax but how do I establish the value of "ProcessName" from the JSON output beforehand?
I also know how to manipulate an array created in a script but I'm having difficulty here because the json object is being created by the test() function so the normal rules don't seem to apply.
Any help would be appreciated.
Thanks
First, replace your console.log() calls with return statements. Then you can just do
var json = test();
var processes = json["AutoScalingGroups"][0]["Suspended Processes"]
updated code:
function test() {
autoscaling.describeAutoScalingGroups(params, function(err, data) {
if (err) {
return [err, err.stack]; // an error occurred
} else {
var json = JSON.stringify(data); // successful response
return json["AutoScalingGroups"][0]["Suspended Processes"];
}
});
}
var processes = test()
console.log(processes);
thanks #RobbieMilejczak, problem resolved:
First, replace your console.log() calls with return statements. Then you can just do
var json = test();
var processes = json["AutoScalingGroups"][0]["Suspended Processes"]
updated code:
function test() {
autoscaling.describeAutoScalingGroups(params, function(err, data) {
if (err) {
return [err, err.stack]; // an error occurred
} else {
var json = JSON.stringify(data); // successful response
return json["AutoScalingGroups"][0]["Suspended Processes"];
}
});
}
var processes = test()
console.log(processes);
I want to have posts + attachments from Facebook so I can create a list of posts. The problem is that I want to put attributes: id, message and any attachment in a array for every post feed. I'm not sure whether I need to iterate objects inside a array or can I select the ID and get the related information.
Also I'm using async.waterfall() to get synchronous calls because I will make other calls that depend on the previous call.
I tried this to get the id, message and src url of attachment:
var async = require("async");
var graph = require('fbgraph');
async.waterfall([
getFeed,
getPostPicture,
], function (err, result) {
});
function getFeed(callback) {
graph.get("/.../feed" + "?fields=message,attachments&access_token=APPID|APPSECRET", function(err, res) {
callback(null, res);
});
}
function getPostPicture(arg1, callback) {
var feedData = arg1.data;
for(var i in feedData)
{
var id = feedData[i].id;
var message = feedData[i].message;
var feedAttachment = feedData[i].attachments
for (var j in feedAttachment)
{
var attachment = feedAttachment.data;
var attachmentURL = attachment[i].src;
for (var j in attachmentURL)
{
var attachmentURL = feedAttachment.src;
}
}
}
console.log(attachment);
}
Above will output:
[ { description: 'post message 1',
media: { image: [Object] },
target:
{ id: '...',
url: 'https://www.facebook.com/.../photos/a............/.../?type=3' },
title: 'Timeline Photos',
type: 'photo',
url: 'https://www.facebook.com/.../photos/a............/.../?type=3' } ]
Below is the response where I first called graph.get in the source code
and I need { data -> [message, id, attachments -> data[src] ]}
{
"data": [
{
"message": "post message 1",
"id": "..._...",
"attachments": {
"data": [
{
"description": "picture 1",
"media": {
"image": {
"height": 256,
"src": "https://scontent.xx.fbcdn.net/v/t1.0-9/..._..._..._n.png?oh=...&oe=...",
"width": 256
}
},
"target": {
"id": "...",
"url": "https://www.facebook.com/.../photos/a............/.../?type=3"
},
"title": "Timeline Photos",
"type": "photo",
"url": "https://www.facebook.com/.../photos/a............./..../?type=3"
}
]
}
},
{
"message": "Test status update 123",
"id": "..._..."
}
],
"paging": {
"previous": "https://graph.facebook.com/v2.8/.../feed?fields=message,attachments&format=json&since=...&access_token=...&limit=25&__paging_token=enc_...&__previous=1",
"next": "https://graph.facebook.com/v2.8/.../feed?fields=message,attachments&format=json&access_token=...&limit=25&until=...&__paging_token=enc_..."
}
}
When you are using the for loop in getPostPicture function, the i variable is actually the element in the array feedData, so you have to i.id or i.attachments and i.message. Also I think since you are using same j in 2 loops with one nested inside the other, it also won't work properly, so you might have to change that also, and explain you question with the kind of output you are expecting.
Im using the $.get to get JSON file content which is working fine,currently I want to filter and get the item with Id 4 (the last one) ,how should I do that ?
in the Jquery doc I didn't find some hint to it...
http://api.jquery.com/jquery.get/
this is the code:
$.get('tweets.json');
this is the JSON file content
[
{
"id": 1,
"tweet": "OMG, worst day ever, my BF #BobbyBoo dumped me",
"usersMentioned": [
{
"id": 10,
"username": "BobbyBoo"
}
]
},
{
"id": 2,
"tweet": "OMG, best day ever, my BF came back to me"
},
{
"id": 3,
"tweet": "OMG, worst day ever, just don't ask"
},
{
"id": 4,
"tweet": "#BobbyBoo OMG...just OMG!",
"usersMentioned": [
{
"id": 10,
"username": "BobbyBoo"
}
]
}
]
update
Currenlty when I try the following I dont get anthing in the then(function (tweets) ,tweets is emtpy
the value entry4 is filled with the correct value...
$.get('profile.json').then(function (profile) {
$('#profile-pre').html(JSON.stringify(profile));
$.get('tweets.json', null, null, 'json')
.then(function (response) {
var entry4 = response.filter(function (tweet) {
return tweet.id === 4;
})[0];
return entry4 ;
})
}).then(function (tweets) {
$('#tweets-pre').html(JSON.stringify(tweets));
var myFriend = $.get('friend.json');
return myFriend
}).then(function (friend) {
That would be
$.get('tweets.json',null,null,'json')
.then(function(response){
var iAmNumberFour = response.filter(function(tweet){
return tweet.id === 4;
})[0];
});
Added the type since if you don't pass the right headers, jQuery won't parse the JSON for you.
$.get('profile.json').then(function(profile) {
$('#profile-pre').html(JSON.stringify(profile));
return $.get('tweets.json', null, null, 'json')
.then(function(response) {
var entry4 = response.filter(function(tweet) {
return tweet.id === 4;
})[0];
return entry4;
})
}).then(function(entry4) {
$('#tweets-pre').html(JSON.stringify(tweets));
var myFriend = $.get('friend.json');
return myFriend
})