How can I access a JSON file in ECMAScript 6?
The following doesn't work:
import config from '../config.json'
This works fine if I try to import a JavaScript file.
https://www.stefanjudis.com/snippets/how-to-import-json-files-in-es-modules-node-js/
ES modules are still reasonably new in Node.js land (they're stable since Node 14). Modules come with a built-in module system, and features such as top-level await.
I read an informative post on ES modules by Pawel Grzybek and learned that you can't import JSON files in ES modules today.
import info from `./package.json` assert { type: `json` };
const { default: info } = await import("./package.json", {
assert: {
type: "json",
},
});
That's a real bummer because I'm pretty used to doing require
calls such as const data = require('./some-file.json')
in Node.js.
But can you use import assertions in Node.js today?
At the time of writing, the current Node.js LTS (v18.12) still marks import assertions as experimental.
This post explains ways to deal with JSON
in ES modules if you don't want to use the experimental feature yet.
The Node.js documentation advises to use the fs
module and do the work of reading the files and parsing it yourself.
import { readFile } from 'fs/promises';
const json = JSON.parse(
await readFile(
new URL('./some-file.json', import.meta.url)
)
);
require
function to load JSON filesThe documentation also states that you can use createRequire
to load JSON files. This approach is the way Pawel advises in his blog post.
createRequire
allows you to construct a CommonJS require
function to use typical CommonJS features such as reading JSON in your Node.js EcmaScript modules.
import { createRequire } from "module";
const require = createRequire(import.meta.url);
const data = require("./data.json");
Importing JSON using ES modules was submitted as feature to TC39 in mid 2020, and is (at the time of this edit) in stage 3, which is the last stage before being accepted in to the spec (see https://github.com/tc39/proposal-json-modules for more details). Once landed, you will be able to use it as:
import someName from "./some/path/to/your/file.json";
Where someName
is effectively the name of the variable for the JS object described by the JSON data. (And of course, note that this imports JavaScript from a JSON source, it does not "import JSON").
If you're using a modern enough bundler (like esbuild
or the like) or you're using a recent enough transpiler (like babel
) then you can already use this syntax without having to worry about support.
Alternatively, if you have the luxury of ownership of JSON files you can also turn your JSON into valid JS files with a minimum of extra code:
config.js
export default
{
// my json here...
}
then...
import config from '../config.js'
does not allow import of existing .json files, but does a job.