How to Read and Write JSON with NodeJS
In this tutorial we will go over how read and write a JSON file with NodeJS. It should come at no surprise that Node makes working with JSON extremely easy, and with the built in fs module, reading and writing to the file system is equally easy.
This tutorial is written in two parts, the first will cover reading from a JSON file, the second part will cover writing to a JSON file.
Reading a file TLDR: To read a file you can either usereadFilewhich will read a file asynchronously, and you need to pass a file path, options and a callback, or you can usereadFileSync, which will read the file synchronously, and you just pass in a file path and options, this function will return the files data.
Writing a file TLDR: To write to a file you can either usewriteFilewhich will write a file asynchronously, and you need to pass in a file path, the data you want to write, your options and a callback to handle errors. Or, you can usewriteFileSync, which will write the file synchronously, and you need to pass a file path, the data you want to write and your options.
Index
- Reading a file with readFile
- Reading a file with readFileSync
- Writing a file with writeFile
- Writing a file with writeFileSync
Before we get started, this is the data that I am working with, and I have this in a file called testJsonFile.json which is in my root directory:
{
"frameworks": [
"express",
"feathers js",
"meteor",
"koa"
]
}
Now that we have the data setup, let's look at the first two lines of my index.js file:
const fs = require('fs')
let parsedJsonData
On the first line, we require the fs module. We will need this to read and write to the file system and we will use this throughout the tutorial.
On the next line we setup a variable that we will use later to store the JSON data that has been read from the file system, we will then add an additional JavaScript framework to that data and then write it back to the file system.
Reading a JSON file
The fs module provides a couple of popular ways to read a file, namely these are, readFile and readFileSync. We will use both of these functions, depending on your situation, reading a file synchronously might not be an issue at all, it also makes it a bit easier in my opinion as we don't need to deal with callbacks.
Reading a file with readFile
I am going to start with the code, and then I will explain it afterwards:
// 1
fs.readFile('./testJsonFile.json', 'utf8', (error, data) => {
// 2
if (error) {
console.log(`ERROR: ${error}`)
return
}
// 3
const jsonData = JSON.parse(data)
// 4
parsedJsonData = jsonData
// 5
// Check the keys that jsonData has
console.log(Object.keys(jsonData))
// 6
jsonData.frameworks.forEach(framework => {
console.log(`Framework: ${framework}`)
})
})
Ok, let's run through what is happening in the above code snippet:
- This is the call to the
readFilefunction. It takes a few arguments, the first being the path to the file you want to read, the second being theoptionsyou want to pass in, we are passing inutf-8for the encoding, and then the last argument is a callback. - The first part of the callback, we are just making sure that an
errordoes not exist, if it does, we will write the error to the console, and return. Using areturnhere is a personal preference. If I can stay away from usingelsethen I generally will, but, you could use anif elseinstead and have the rest of the code be in theelseblock. - Here we parse the
datawhich is the second argument for the callback, and we assign the parsed data to thejsonDataconstant. - We can now assign the parsed JSON data to the global variable that we created at the start of the tutorial, we will use this later when writing to the file system.
- This isn't an important line, but we are just printing out all the
keysof thejsonDataobject. For the sake of this tutorial, this makes it easier to see thekeysthat the test data has. - Lastly, we loop through the
frameworksand print it to the console.
And that is it! That is how simple it is to read a json file asynchronously using Node.
Reading a file with readFileSync
Once again, let's start with the code:
// 1
try {
// 2
const data = fs.readFileSync('./testJsonFile.json', 'utf8')
// 3
const jsonData = JSON.parse(data)
// 4
parsedJsonData = jsonData
// 5
// Check the keys that jsonData has
console.log(Object.keys(jsonData))
// 6
jsonData.frameworks.forEach(framework => {
console.log(`Framework: ${framework}`)
})
} catch (error) { // 7
console.log(`ERROR: ${error}`)
}
Most of the steps are quite similar to the asynchronous example, the big difference is the try catch.
- We need use a
try catchbecausereadFileSynccan throw an error. In the asynchronous example, this error would be passed as an argument to the callback, but the synchronous version does not use a callback, so the function itself will throw an error and we need to handle that. - We use the
readFileSyncfunction to read the file. The first argument is the file path and the second argument is for options. Again, for the second argument, we pass through the encoding that we want to use. ThereadFileSyncfunction returns the data immediately. which is why we assign it to a constant. - Now, we can parse the
dataas we have before by usingJSON.parse. - We assign the parsed data to our
parsedJsonDataglobal variable so that we can use the data later on. - Print out the
keysof the JSON object, which helps for debugging, and just makes things a bit clearer in a tutorial. - We loop through all the values for the
frameworkskey, and print those values to the console. - As mentioned before, we need a
try catchbecause of the wayreadFileSyncworks, and this is where we catch the error and print it to the console.
As I have mentioned before, this is my preferred way to read files because it is so straight forward, but, making use of the readFileSync function heavily depends on what your use case is.
Writing a JSON file
In the previous section we spoke about reading a file using the fs module. Writing to the file system also uses the fs module, and it too has two functions that we will use. Namely, writeFile and writeFileSync. This works in a similar way to the read functions.
Writing a file with writeFile
Let's start with the code:
// 1
parsedJsonData.frameworks.push('nest js')
// 2
const asyncFrameworksData = JSON.stringify(parsedJsonData)
// 3
fs.writeFile('./testJsonFile.json', asyncFrameworksData, 'utf-8', (error) => {
// 4
if (error) {
console.log(`WRITE ERROR: ${error}`)
} else {
// 5
console.log('FILE WRITTEN TO')
}
})- We are now going to make use of the
parsedJsonDatathat we created at the beginning of the tutorial. SinceparsedJsonDataalready contains a JSON object, we can push an additional element,next js, onto theframeworksproperty. - Before we write to the file, we need to stringify the JSON object.
- Now that we have updated and stringified
parsedJsonData, we can writeasyncFrameworksDatato our file. To write to a file we use thewriteFilefunction from thefsmodule. The first argument is the file path, the second argument is the data we want to write, in our caseasyncFrameworksData, the third argument is foroptions, once again we are going to use it to set our encoding toutf-8. Lastly, we need to pass in a callback. This callback only takes one argument, and that is for an error. - We check if an error exists, if it does we will print it in the console.
- If there is no error, we print to the console that the file has been written to.
That is all that is needed to write to a file asynchronously, just as easy, if not easier than reading a file.
Writing a file with writeFileSync
Starting with the code one again:
// 1
parsedJsonData.frameworks.push('nest js')
// 2
try {
// 3
const frameworksData = JSON.stringify(parsedJsonData)
// 4
fs.writeFileSync('./testJsonFile.json', frameworksData, 'utf-8')
} catch (error) { // 5
console.log(`WRITE ERROR: ${error}`)
}
- If you have read the
writeFilesection, we are doing the same thing, we simply add a new element to the frameworks array in theparsedJsonDataobject. - Because there is no callback provided to the
writeFileSyncfunction, it will throw an error if there is an issue, so we need to wrap it in atry catchblock. - Same as the previous section. Before we write the data, we need to stringify it.
- We write the data to the specified file path. Similarly to
writeFile,writeFileSynctakes the file path as the first argument, the data we want to write,frameworksData, as the second argument and lastly it takes an options argument, which we use to pass the encoding that we want, which isutf-8. - This follows on from point 2, in the catch part of the
try catchwe catch any errors and then we will print those to our console.
The original data in the testJsonFile.json looked like this:
{
"frameworks": [
"express",
"feathers js",
"meteor",
"koa"
]
}After we write to it, it should look like this:
{
"frameworks": [
"express",
"feathers js",
"meteor",
"koa",
"nest js"
]
}Conclusion
This tutorial was quite long, but the code itself is quite easy. Reading from a file and writing to a file synchronously is easier than asynchronously, simple because you do need the callback, and everything works as expected.
If you need to read the file asynchronously and then write to it afterwards, remember that you need to handle the writing from within callback, otherwise you could read a file, and while you are reading the file, the write could have already happened.
You can find all the source code here.