How to update json entry in node.js - javascript

How can I update json value with node.js? I found in internet couple examples but my is a little bit more complicated
I can open value I want to change
var contents = fs.readFileSync("./../../skill.json");
var jsonContent = JSON.parse(contents);
console.log("Address", jsonContent['manifest']['apis']['custom']['endpoint']['uri']);
but how to edit it with my value?

var contents = fs.readFileSync("./../../skill.json");
var jsonContent = JSON.parse(contents);
console.log("Address", jsonContent['manifest']['apis']['custom']['endpoint']['uri']);
// modify your value
jsonContent['manifest']['apis']['custom']['endpoint']['uri'] = 'new value';
// stringify it and write to file
fs.writeFileSync("./../../skill.json", JSON.stringify(jsonContent));

Assignment in JavaScript is done via the assignment operator (=).
Accessing values of an object can be done via the property accessors (. and []).
Hence, modifying the content is as straightforward as
jsonContent['manifest']['apis']['custom']['endpoint']['uri'] = 'value';
Or even:
jsonContent.manifest.apis.custom.endpoint.uri = 'value';
That being said, I would suggest to at least wrap the assignment in a try catch block so that you are not exposed to a crash if the object does not deeply match the structure you expect to receive.
A more robust and versatile solution would be to leverage Lodash.set. For example:
_.set(jsonContent, ['manifest', 'apis', 'custom', 'endpoint', 'uri'], 'value');
As noted by #Patrick Roberts, modern JavaScript will allow leveraging the optional chaining operator ?.. This is currently only available in stage 1.
jsonContent?.manifest?.apis?.custom?.endpoint?.uri = 'value';

const {promisify} = require('util');
const fs = require('fs');
const readFile = promisify(fs.readFile);
const writeFile = promisify(fs.writeFile);
(async (){
try {
var contents = await readFile("./../../skill.json");
var jsonContent = JSON.parse(contents);
console.log("Address", jsonContent.manifest.apis.custom.endpoint.uri);
// modify your value
jsonContent.manifest.apis.custom.endpoint.uri = 'new value';
// stringify it and write to file
await writeFile("./../../skill.json", JSON.stringify(jsonContent));
} catch (e){
console.error(e);
}
})();

Related

Define template strings as const to evaluate later

Is there a way to accomplish something like this:
const API_URL = `https://api.my-data-provider.com/items/${id}`
// [...]
// and later on or in another file, use it with something like
const result = await fetch(API_URL(id)) // or API_URL.apply(id), API_URL.apply({ id: 23}), etc...
I want to save template literals in a constants / configuration file, to use them later
Or is there any other standard or well established way to do this kind of thing?
You could use a function for this:
const generateApiUrl = (id) => `https://api.my-data-provider.com/items/${id}`;
const result = await fetch(generateApiUrl(id))

txt file to json using Node JS

I have a simple txt file with data in this format with millions of lines:
{"a":9876312,"b":1572568981512}
{"a":9876312,"b":1572568981542}
I want to convert this into a file with "dot" json extension file using reduce function in NodeJs and return statement, probably looking like this:
[{"a":9876312,"b":1572568981512},
{"a":9876312,"b":1572568981542}]
Any help will be really really appreciated. Thanks :)
SO far I tried this:
const fs = require('fs');
const FILE_NAME = 'abc.txt';
const x = mapEvents(getJSONFileData(FILE_NAME));
function getJSONFileData(filename) {
return fs.readFileSync(filename, 'utf-8')
.split('\n')
.map(JSON.parse)
}
function mapEvents(events) {
events.reduce((acc, data) => {
return [{data.a, data.b}]
});
}
console.log(x)
I am getting an 'undefined' value constantly
I have found some issues, in your code.
You haven't returned anything from mapEvents function, that makes your varaible x value undefined.
getJSONFileData needs some fixing.
You can use below code:-
const fs = require('fs');
const FILE_NAME = 'abc.txt';
const x = mapEvents(getJSONFileData(FILE_NAME));
function getJSONFileData(filename) {
return fs
.readFileSync(filename, 'utf-8')
.split('\n')
.filter(Boolean)
.map(JSON.parse);
}
function mapEvents(events) {
return JSON.stringify(events);
}
console.log(x);

Node js reuse existing buff call

I use the following code which works as expected however I wonder if there is a way to improve is as Im doing New Buffer twice.
I need to encode two values now but more latter... , user and password.
I mean reduce boilerplate code
let secret = await getSecret("mt", "fe");
let adminBuff = new Buffer(secret.admin, 'base64');
let admin = adminBuff.toString('ascii');
let adminPass = new Buffer(secret.pass, 'base64');
let pass = adminPass.toString('ascii');
Use Buffer.from() since new Buffer is deprecated.
As for the reusability part, creating a function would be helpful. Something like the following:
function toAsciiString (value) {
const valueBuff = Buffer.from(value, 'base64');
return valueBuff.toString('ascii');
}
let secret = await getSecret("mt", "fe");
let admin = toAsciiString(secret.admin);
let pass = toAsciiString(secret.pass);
Hope this helps :)
You can iterate over the keys of the object "secret", process their values and create a new object containing the processing results.
For example:
let secret = await getSecret("mt", "fe");
const resultObj = {};
Object.keys(secret).forEach((key) => {
const newBuffer = new Buffer(secret[key], 'base64');
resultObj[key] = newBuffer.toString('ascii');
});

Fake a Node.js Readable file stream from a JavaScript object

I want to create a "fake file" from a javascript object, as the libarry I am using is expecting a file as input, but I have an object in memory instead.
So it is expecting code something like this
var file = fs.readFileSync('{/path/to/file}');
lib.addDocument(config, file),
I want to create a fake file from a object I have called payload, and send that instead, my closest attempt so far looks like this:
var fake_file = new stream.Readable({ objectMode: true });
fake_file.push(msg.payload);
fake_file.push(null);
lib.addDocument(config, fake_file),
I feel I am close, but I cant quite get it to work. Current error is
{ Error: Unexpected end of multipart data
var Readable = require('stream').Readable
var obj = { objectMode : true};
var rStream = new Readable
rStream.push(JSON.stringify(obj));
rStream.push(null); //EOF
lib.addDocument(config, rStream)
For older versions below v10 and above v4:
var Readable = require('stream').Readable
var obj = { objectMode : true};
var chars=JSON.stringify(obj).split('');
function read(n){this.push(chars.shift())}
var rStream = new Readable({read:read});
lib.addDocument(config, rStream)
Your code is missing an Object -> String conversion. May use JSON.stringify for that:
lib.addDocument(config, JSON.stringify(msg.payload));

TypeError: Converting circular structure to JSON in nodejs

I am using request package for node.js
Code :
var formData = ({first_name:firstname,last_name:lastname,user_name:username, email:email,password:password});
request.post({url:'http://localhost:8081/register', JSON: formData}, function(err, connection, body) {
exports.Register = function(req, res) {
res.header("Access-Control-Allow-Origin", "*");
console.log("Request data " +JSON.stringify(req));
Here I am getting this error :
TypeError: Converting circular structure to JSON
Can anybody tell me what is the problem
JSON doesn't accept circular objects - objects which reference themselves. JSON.stringify() will throw an error if it comes across one of these.
The request (req) object is circular by nature - Node does that.
In this case, because you just need to log it to the console, you can use the console's native stringifying and avoid using JSON:
console.log("Request data:");
console.log(req);
I also ran into this issue. It was because I forgot to await for a promise.
Try using this npm package. This helped me decoding the res structure from my node while using passport-azure-ad for integrating login using Microsoft account
https://www.npmjs.com/package/circular-json
You can stringify your circular structure by doing:
const str = CircularJSON.stringify(obj);
then you can convert it onto JSON using JSON parser
JSON.parse(str)
I was able to get the values using this method, found at careerkarma.com
Output looks like this.
I just run this code in the debugger console. Pass your object to this function.
Copy paste the function also.
const replacerFunc = () => {
const visited = new WeakSet();
return (key, value) => {
if (typeof value === "object" && value !== null) {
if (visited.has(value)) {
return;
}
visited.add(value);
}
return value;
};
};
JSON.stringify(circObj, replacerFunc());
I forgotten to use await keyword in async function.
with the given systax
blogRouter.put('/:id', async (request, response) => {
const updatedBlog = Blog.findByIdAndUpdate(
request.params.id,
request.body,
{ new: true }
);
response.status(201).json(updatedBlog);
});
Blog.findByIdAndUpdate should be used with the await keyword.
use this https://www.npmjs.com/package/json-stringify-safe
var stringify = require('json-stringify-safe');
var circularObj = {};
circularObj.circularRef = circularObj;
circularObj.list = [ circularObj, circularObj ];
console.log(stringify(circularObj, null, 2));
stringify(obj, serializer, indent, decycler)
It's because you don't an async response For example:
app.get(`${api}/users`, async (req, res) => {
const users = await User.find()
res.send(users);
})
This is because JavaScript structures that include circular references can't be serialized with a"plain" JSON.stringify.
https://www.npmjs.com/package/circular-json mentioned by #Dinesh is a good solution. But this npm package has been deprecated.
So use https://www.npmjs.com/package/flatted npm package directly from the creator of CircularJSON.
Simple usage. In your case, code as follows
import package
// ESM
import {parse, stringify} from 'flatted';
// CJS
const {parse, stringify} = require('flatted');
and
console.log("Request data " + stringify(req));
If you are sending reponse , Just use await before response
await res.json({data: req.data});
Came across this issue in my Node Api call when I missed to use await keyword in a async method in front of call returning Promise. I solved it by adding await keyword.
I was also getting the same error, in my case it was just because of not using await with Users.findById() which returns promise, so response.status().send()/response.send() was getting called before promise is settled (fulfilled or rejected)
Code Snippet
app.get(`${ROUTES.USERS}/:id`, async (request, response) => {
const _id = request.params.id;
try {
// was getting error when not used await
const user = await User.findById(_id);
if (!user) {
response.status(HTTP_STATUS_CODES.NOT_FOUND).send('no user found');
} else {
response.send(user);
}
} catch (e) {
response
.status(HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR)
.send('Something went wrong, try again after some time.');
}
});
For mongodb
so if you are getting errors while fetching data from MongoDB then the problem is async
previously
app.get('/users',(req,res,next)=>{
const user=chatUser.find({});
if(!user){
res.status(404).send({message:"there are no users"});
}
if(user){
res.json(user);
}
})
After
app.get('/users',async(req,res,next)=>{
const user=await chatUser.find({});
if(!user){
res.status(404).send({message:"there are no users"});
}
if(user){
res.json(user);
}
})
I came across this issue when not using async/await on a asynchronous function (api call). Hence adding them / using the promise handlers properly cleared the error.
This error message "TypeError: Converting circular structure to JSON" typically occurs when you try to stringify an object that contains circular references using JSON.stringify().
A circular reference occurs when an object references itself in some way. For example, consider the following code:
const obj = { foo: {} };
obj.foo.obj = obj;
In this example, obj contains a circular reference because the foo property of obj contains a reference to obj itself.
When you try to stringify an object like this using JSON.stringify(), it will fail with the error message "TypeError: Converting circular structure to JSON".
To solve this issue, you can use a third-party library like flatted or circular-json, which are specifically designed to handle circular references in JavaScript objects. Here's an example using flatted:
const flatted = require('flatted');
const obj = { foo: {} };
obj.foo.obj = obj;
const str = flatted.stringify(obj);
console.log(str);
In this example, we use flatted.stringify() instead of JSON.stringify(), and it successfully converts the object to a string without throwing an error.
Alternatively, you can modify your object to remove the circular reference before trying to stringify it. For example:
const obj = { foo: {} };
obj.foo.bar = 'baz';
// add circular reference
obj.foo.obj = obj;
// remove circular reference
obj.foo.obj = undefined;
const str = JSON.stringify(obj);
console.log(str);
In this example, we add the circular reference and then remove it before trying to stringify the object. This approach works well if you don't need to preserve the circular reference in the stringified object.
I had a similar issue:-
const SampleFunction = async (resp,action) => {
try{
if(resp?.length > 0) {
let tempPolicy = JSON.parse(JSON.stringify(resp[0]));
do something
}
}catch(error){
console.error("consoleLogs.Utilities.XXX.YYY", error);
throw error;
}
.
.
I put await before JSON.parse(JSON.stringify(resp[0])).
This was required in my case as otherwise object was read only.
Both Object.create(resp[0]) and {...resp[0]} didn't suffice my need.
If an object has a different type of property like mentioned in the above image, JSON.stringify() will through an error.
Try this as well
console.log(JSON.parse(JSON.stringify(req.body)));
TypeError: Converting circular structure to JSON in nodejs:
This error can be seen on Arangodb when using it with Node.js, because storage is missing in your database. If the archive is created under your database, check in the Aurangobi web interface.

Categories