How should I import JSON in Node?

Viewed 4035

I want to import package.json into test.js, both files are in same directory.

I tried with require :

const jsonfile = require("./packages.json");

console.log({ jsonfile });

it throws error:

file:///home/.../test.js:1
const jsonfile = require("./packages.json");
                 ^
ReferenceError: require is not defined
    at file:///home/.../test.js:1:18
    at ModuleJob.run (internal/modules/esm/module_job.js:145:37)
    at async Loader.import (internal/modules/esm/loader.js:182:24)
    at async Object.loadESM (internal/process/esm_loader.js:68:5)

This error implies, like it runs in browser, where is no require, I found an answer with similar message.

I tried with import:

import * as jsonfile from './packages.json';

console.log({ jsonfile });
internal/process/esm_loader.js:74
    internalBinding('errors').triggerUncaughtException(
                              ^

Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/home/.../packages.json' imported from /home/.../test.js
    at finalizeResolution (internal/modules/esm/resolve.js:271:11)
    at moduleResolve (internal/modules/esm/resolve.js:694:10)
    at Loader.defaultResolve [as _resolve] (internal/modules/esm/resolve.js:784:11)
    at Loader.resolve (internal/modules/esm/loader.js:100:40)
    at Loader.getModuleJob (internal/modules/esm/loader.js:246:28)
    at ModuleWrap.<anonymous> (internal/modules/esm/module_job.js:47:40)
    at link (internal/modules/esm/module_job.js:46:36) {
  code: 'ERR_MODULE_NOT_FOUND'
}

What I have tried more?

  • Single quotes and double quote around filename
  • filename with extension and without.
  • with flag --experimental-json-modules
  • adding "type":"module into package.json (but this is for Node >= 13, but without it I got warning (node:7170) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension. and then also error SyntaxError: Cannot use import statement outside a module)

I found even suggestions to load JSON-file as regular text files and parse them into data structure, but this seems like the last resort...

It seems such a trivial task, but I have not found the idiomatic way how to import JSON-data into Javascript variable. What is wrong here? How should I import it?

I use Node 12.21.0

3 Answers

You're using Node.js in ESM mode, ESM does not currently import JSON modules by default. You can either:

  1. Turn on JSON module importing (by passing a CLI flag) OR
  2. Create a require function in your ESM code and use that OR
  3. JSON.parse the file manually

Turn on JSON module importing (by passing a CLI flag)

You can do that by passing the --experimental-json-modules flag.

node --experimental-json-modules yourfile.js # can import JSON here

Create a require function in your ESM code

You can also always fall back on CommonJS modules and create a require of your own:

import { createRequire } from 'module';
const require = createRequire(import.meta.url);
require('./package.json'); // now works

JSON.parse the file manually

You can always just read JSON files with regular filesystem methods:

# const fs = require('fs');
import * as fs from 'fs';
const result = JSON.parse(fs.readFileSync('./package.json'));

You want to import package.json but in your code you tried to import packages.json (there is a typo).

Note that when you use ESM (import ... from ... syntax), you cannot import .json files directly and require will not be defined (on nodejs), while in CJS you can load a json file with require(...) syntax (see https://nodejs.org/api/esm.html#esm_no_json_module_loading).

Also, note that you can create a CJS file which imports a JSON file and exports its content, so you can later import it from an ESM file.

pkg.cjs (CJS)

const pkg = require('./package.json');
module.exports = pkg;

index.mjs (ESM)

import pkg from './pkg.cjs';
console.info(`Starting ${pkg.name} v${pkg.version}`);

The import syntax should be always working, but in this case you are requiting it wrong. Try import jsonfile from './packages.json';. Youn don't need the * in this case

Related