Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
Ben Nadel at cf.Objective() 2014 (Bloomington, MN) with: Dan Wilson
Ben Nadel at cf.Objective() 2014 (Bloomington, MN) with: Dan Wilson@DanWilson )

You Can Use require() To Load JSON (JavaScript Object Notation) Files In Node.js

By Ben Nadel on

At InVision App, we're hiring a lot of Node.js developers. Which means, I get to look at a lot of Node.js sample code. And, one odd thing, that I keep seeing over and over again, is developers using JavaScript modules to define static JSON (JavaScript Object Notation) configuration files. I think maybe they do this because they don't know that you can require() a JSON file in Node.js. As such, I wanted to put together a quick demo.


 
 
 

 
 
 
 
 

The require() function, in Node.js, can read in both .js and .json files. If a file ends with .js, the file is parsed and interpreted as a JavaScript file and is expected to use the module syntax. And, if the file ends with .json, the file is parsed and interpreted as a JSON text file and is expected to adhere to the JSON syntax.

To see this in action, let's create two configuration files: config.js and config.json. The first - config.js - is what I keep seeing in submitted Node.js code samples:

  • module.exports = {
  • server: "localhost",
  • port: 1234,
  • timeout: 10
  • };

Here, you can see the developer is using the module syntax; but, is really only exposing static configuration data. Now, let's create another file - config.json - which contains truly static configuration data:

  • {
  • "server": "localhost",
  • "port": 1234,
  • "timeout": 10
  • }

Ok, now let's try to read in both of these files using the require() method and log the result out to see what Node.js is doing:

  • // When loading a configuration file, we have the choice to load either .js file,
  • // which will be interpreted as a JavaScript module file, with the "exports" being
  • // returned from the require; or, we can load a .json file, which will be parsed as
  • // JavaScript Object Notation (JSON) with the result being returned from the require.
  •  
  • // Load configuration as JSON.
  • console.log( "JSON File:" );
  • console.log( require( "./config.json" ) );
  •  
  • // Load configuration as module.
  • console.log( "MODULE File:" );
  • console.log( require( "./config.js" ) );

When we run this code, we get the following terminal output

ben$ node explicit-ext.js
JSON File:
{ server: 'localhost', port: 1234, timeout: 10 }
MODULE File:
{ server: 'localhost', port: 1234, timeout: 10 }

As you can see, both approaches - requiring a .js and requiring a .json file - result in the same outcome: exposure of a JavaScript hash of configuration information.

At this point, you might be thinking that being able to require a .json file is nice; but, that you don't want to paint yourself into a "static" corner. Sure, you might start out with static configuration files; but, down the road, you might need to do a little post-read "data massaging."

This is no problem. All we have to do is omit the file extension and Node.js will look for a .js file first and then, if not found, look for a .json file. This means that we can start off using a completely static .json file, move to a .js file later on, and the calling code doesn't have to change at all.

To see this in action, let's try to require() a .json file without an explicit file extension:

  • // When loading a configuration file, we don't have to lock ourselves into a particular
  • // type of file. If we exclude the file-extension, Node will automatically try to look
  • // for a *.js and then, if not found, a *.json file. This means that we can start out
  • // using a .json file; then, if we need to add a programmatic aspect to the config file,
  • // we can transparently change it over to a "module" style file. The take-away here is
  • // that there is absolutely no reason to NOT start out with a .json file if your module
  • // just returns a static hash.
  •  
  • // Load configuration as UNKNOWN file type.
  • // --
  • // NOTE: On disk, it is "config.json". But, we're going to make Node.js look for it.
  • console.log( "UNKNOWN File:" );
  • console.log( require( "./config" ) );

Here, we're using the require() method to read in a file without an obvious file extension, although we do have a .json file on disk. And, when we run this code, we get the following terminal output:

ben$ node implicit-ext.js
UNKNOWN File:
{ server: 'localhost', port: 1234, timeout: 10 }

As you can see, it worked perfectly. This means that we can start out with a .json file. Then, over time, if we needed to make the application configuration more dynamic, we could seamlessly and transparently switch over to using a .js file. Such is the power of the require() method in Node.js.




Reader Comments

I have a few things that need to be configured for almost every application I create: loggers, email server, databases, errorhandlers etc and also a few application specific items like application name, port.

I created a node module dvconfigure and published it as an npm private package. It exposes one function which takes the path to two json files (common,and application) and an app object.
I use nconf to grab those config files and attach them to the app object.

When I start an application I just use:

require("@donvawter/dvconfigure")app,__dirname+"/common_config.json",__dirname+"/app_config.json")
.then(....)
.catch(...)

From the command line I often use the require method to validate a json file.
Just get in node REPL with node <ENTER>
and then type
foo=require("./package.json")
If I forgot a comma somewhere I know it immediately.

Reply to this Comment

@Don,

Very interesting! I haven't done too much "production" node.js stuff yet; but, I think our team uses something similarish. I think we have a "core" node module that we sort of use as the bootstrap for all of the applications. It sets up things like what you mention - loggers, mongoDB connectors, etc.

But, I haven't had a chance to really dig into that stuff yet.

Reply to this Comment

I didn't know this and used it the other day when I was testing stuff out in the REPL and had a .json file I wanted to walk through. Definitely saves a few steps requiring the .json file as opposed to requiring fs and reading the file in, especially when messing around in the REPL

Reply to this Comment

On the plus side, using a ".js" file means you don't have to use strict JSON format. Hence:

{
foo: 'blah',
bar: foo + '/blah.html' // this must be an HTML file
}

rather than

{
"foo": "blah",
"bar": "blah/blah.html"
}

Reply to this Comment

Hello, I'm new with this kind of things. I have two files .js running, one on port 3000 and the other on the 4000. The one running on the port 4000 has a json message that I want to receive in the 3000 console.

3000:
... var request = require('request-json');
var client = request.createClient('http://localhost:4000/'); ...

4000:
app.get('/Teste2', function(req, res){
var jsonmsg= {"MSg":"teste"};
res.json(jsonmsg);
})

Can someone give me an advice please?

Reply to this Comment

Post A Comment

You — Get Out Of My Dreams, Get Into My Comments
Live in the Now
Oops!
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.