5

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

w.k
  • 8,218
  • 4
  • 32
  • 55
  • You should be able to `require` a json file in Node, not sure what is going wrong. – olawrdhalpme Mar 20 '21 at 20:55
  • The current LTS for Node is 14, and the current stable is 15, so at the very least you probably want to update to 14, but if you _have_ to use 12: you're not writing ES module code, why would you try to force Node into running your code as if it is? Just run `node test.js` (not `node test`), and your code will run just fine. – Mike 'Pomax' Kamermans Mar 20 '21 at 20:56
  • `require("./file.json");` should work. Is it just a typo? package**s**.json vs. package.json? – simon.ro Mar 20 '21 at 21:03
  • @simon.ro yes, it was just typo here, in actual code it was `package.json` – w.k Mar 20 '21 at 22:10
  • @Mike'Pomax'Kamermans Thank you for pointing out old version, seems reasonable to upgrade. And I run always with extension. – w.k Mar 20 '21 at 22:11

5 Answers5

13

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'));
Benjamin Gruenbaum
  • 270,886
  • 87
  • 504
  • 504
  • I am not sure if `--experimental-json-modules` works on Node.js 12, so you might be down to `createRequire`. – Benjamin Gruenbaum Mar 20 '21 at 21:00
  • 1
    I can confirm: all those 3 variants work fine. With flag `--experimental-json-modules` I did not include extension (was './package'). Thank you! – w.k Mar 20 '21 at 22:08
  • ESM doesn't just not "currently" support JSON, it will never support JSON =) – Mike 'Pomax' Kamermans Mar 20 '21 at 22:51
  • @Mike'Pomax'Kamermans JSON modules reached stage 3 in last month https://github.com/tc39/proposal-json-modules#json-modules and is currently in-development in Chrome https://www.chromestatus.com/feature/5749863620804608 . anything you know I don't regarding the chances of it shipping in browsers or being unflagged? (If TC39 ships it, we'll 100% ship it in Node.js) – Benjamin Gruenbaum Mar 21 '21 at 08:15
  • interesting, I thought it got shot down as proposal, guess that changed since last time I looked. – Mike 'Pomax' Kamermans Mar 21 '21 at 16:37
3

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}`);
Karl.S
  • 2,294
  • 1
  • 26
  • 33
1

I wanted to add context here for those who may be upgrading from node 12 to 16, as I am doing for some AWS stuff I have running.

I found this --> https://nodejs.org/docs/latest-v16.x/api/esm.html#import-assertions when dealing with import assertions.

Worked for me as I am working through and upgrading my project to use the new import syntax.

Which means you could just

import jsonfileData from './packages.json' assert { type: 'json' };

and it should work. Again, assuming you are upgrading your project to 16.

Thanks,

~Rob

0

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

voxtool
  • 345
  • 4
  • 11
0

Don't.

Convert that JSON into a JavaScript object and save that file as .mjs and import it like normal. For example:

MIME_TYPES.json

{
  "default": "application/octet-stream",
  "aac": "audio/aac",
  "bin": "application/octet-stream",
  "bmp": "image/bmp",
  "css": "text/css",
  "csv": "text/csv"
}

Converts to MIME_TYPES.mjs

export default {
  default: 'application/octet-stream',
  aac: 'audio/aac',
  bin: 'application/octet-stream',
  bmp: 'image/bmp',
  css: 'text/css',
  csv: 'text/csv'
}

Then just import MIME_TYPES from './MIME_TYPES.mjs';

Ronnie Royston
  • 16,778
  • 6
  • 77
  • 91