Search code examples
javascriptnode.jsjsonrequirediscord.js

node.js: require json file returns MODULE NOT FOUND


I'm trying to store a json array to a variable, but node.js return this error: { Error: Cannot find module 'jokes.json'

Here is my code:

let jsonData = require('jokes.json');
var jokes = jsonData.jokes;

The jokes.json file is in the same directory as the javascript file


Solution

  • If you just want the quick answer, you need to change to:

    let jsonData = require('./jokes.json');
    

    to instruct the nodejs module loader to look in the current module's directory for jokes.json. Yes, this is somewhat surprising to a node.js newbie, but there is some method to the madness (see below).


    All the rules for loading modules via a relative path are described here: https://nodejs.org/api/modules.html#modules_all_together. I'd really suggest reading it.

    To make it easier to discuss, I'll include a portion here:

    require(X) from module at path Y
    1. If X is a core module,
       a. return the core module
       b. STOP
    2. If X begins with '/'
       a. set Y to be the filesystem root
    3. If X begins with './' or '/' or '../'
       a. LOAD_AS_FILE(Y + X)
       b. LOAD_AS_DIRECTORY(Y + X)
    4. LOAD_NODE_MODULES(X, dirname(Y))
    5. THROW "not found"
    
    LOAD_AS_FILE(X)
    1. If X is a file, load X as JavaScript text.  STOP
    2. If X.js is a file, load X.js as JavaScript text.  STOP
    3. If X.json is a file, parse X.json to a JavaScript Object.  STOP
    4. If X.node is a file, load X.node as binary addon.  STOP
    
    LOAD_INDEX(X)
    1. If X/index.js is a file, load X/index.js as JavaScript text.  STOP
    2. If X/index.json is a file, parse X/index.json to a JavaScript object. STOP
    3. If X/index.node is a file, load X/index.node as binary addon.  STOP
    
    LOAD_AS_DIRECTORY(X)
    1. If X/package.json is a file,
       a. Parse X/package.json, and look for "main" field.
       b. If "main" is a falsy value, GOTO 2.
       c. let M = X + (json main field)
       d. LOAD_AS_FILE(M)
       e. LOAD_INDEX(M)
       f. LOAD_INDEX(X) DEPRECATED
       g. THROW "not found"
    2. LOAD_INDEX(X)
    
    LOAD_NODE_MODULES(X, START)
    1. let DIRS = NODE_MODULES_PATHS(START)
    2. for each DIR in DIRS:
       a. LOAD_AS_FILE(DIR/X)
       b. LOAD_AS_DIRECTORY(DIR/X)
    
    NODE_MODULES_PATHS(START)
    1. let PARTS = path split(START)
    2. let I = count of PARTS - 1
    3. let DIRS = [GLOBAL_FOLDERS]
    4. while I >= 0,
       a. if PARTS[I] = "node_modules" CONTINUE
       b. DIR = path join(PARTS[0 .. I] + "node_modules")
       c. DIRS = DIRS + DIR
       d. let I = I - 1
    5. return DIRS
    

    Because require('jokes.json') does not start with / or ., your require() statement goes to this:

    4. LOAD_NODE_MODULES(X, dirname(Y))
    

    which then calls

    NODE_MODULES_PATHS(START)
    

    which builds a list of search paths which includes the directory name from which the current script was loaded with an attached "/node_modules" sub-directory any global module install locations. It will not include the directory that the current module was loaded from.