How to import a JSON file in ECMAScript 6?
Asked Answered
S

24

360

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.

Option 1: Read and parse JSON files yourself

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)
  )
);

Option 2: Leverage the CommonJS require function to load JSON files

The 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");
Sibby answered 22/1, 2016 at 10:13 Comment(5)
This has nothing to do with ES6 but with the module loader you are using. The syntax itself is fine.Erlanger
The cleanest way to do this is to use webpack and json-loader with it.Rust
ES6 support JSON importing with the following syntax: import * as data from './example.json';Scent
@Scent That does not work in present-day (2020) browsers unless there's something more going on (e.g. some build step like Babel that rewrites code): e.g. in Chrome one gets “Failed to load module script: The server responded with a non-JavaScript MIME type of "application/json". Strict MIME type checking is enforced for module scripts per HTML spec.” (See spec discussions here and discussions on this proposal repo.) As of now, one needs to use one of the answers below.Glass
The simple answer is don't. Convert the JSON to JavaScript then save as .mjs and import as usual.Andaman
S
173

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.

Stir answered 4/10, 2016 at 14:46 Comment(8)
This doesn't actually answer the question. You can't simply convert your package.json into package.js for example. There are times when you want to truly import JSON not JS.Gainsborough
Not a solution at all, you are exporting a javascript object which happens to have the same syntax as JSON.Important
Updated the issue text; attempt to avoid further semantical debates.Stir
I added a "postbuild": "node myscript.js" step in my package.json file that uses replace-in-file to do this for me. myscript.js ­ const replace = require('replace-in-file'); const options = { files: '_demo/typedocs/navexReact.td.js', from: /{/, to: 'export default {', }; const convertJsonOutputToJsModule = async () => { try { const changes = await replace(options) console.log('Converted json to module in files:', changes.join(', ')); } catch (error) { console.error('Error occurred:', error); } } convertJsonOutputToJsModule() Oxygen
"convert it to JS" is not a solution for how to import a JSON file. That's not JSON file anymore. This is a #1 google result for how to import JSON, and the main answer is to not import JSON.Hodess
Having config in .js file is more convenient, because you can have comments inside. JSON file does not support this.Plumley
The syntax in the proposal has changed.Octangular
At least me was helped a lot with this. I used the assert { type: json` };` style only to learn that FF does not support it yet. I have control of everything so making a .js file out of my .json file is not a problem. My code is nearly untouched - so I can live with it happily, thanks!Wateriness
S
259

In TypeScript or using Babel, you can import json file in your code.

// Babel

import * as data from './example.json';
const word = data.name;
console.log(word); // output 'testing'

Reference: https://hackernoon.com/import-json-into-typescript-8d465beded79

Scent answered 13/6, 2018 at 6:56 Comment(7)
Just to add to this (typescript json import) you can now simply add this to your tsconfig... { "compilerOptions": { "resolveJsonModule": true } }Streamer
Do any browsers support this? I tried this on current FF and get the error Loading failed for the module with source "example.json"; on Chrome I get "Failed to load module script: The server responded with a non-JavaScript MIME type of "application/json". Strict MIME type checking is enforced for module scripts per HTML spec."Pl
@Pl it works on all my browsers. Do you have ES6/ES2015 support enabled?Scent
It just occurred to me, when you say "in ES6" you actually mean "in TS" -- I thought you were talking about the code emitted by tsc but that's not actually what's happening. I'm trying to run ES6 modules natively on the browser (<script type="module">) and the errors above are what you get if you run that import line directly. Please correct me if I'm wrong and you did in fact mean that it's possible to import from JSON in actual ES6.Pl
@Pl i do not know TS and I really meant ES6. I have it working in my ES6 projects via Babble transcribersScent
When I said "Do any browsers support this," I didn't mean "after you transpile it through Babel." The first article you linked has TS transpiling the import statement to a node require() (try it!), and the second link says nothing about JSON imports. The problem here is not with the parser or the module system, it's the loader -- the browser's loader won't resolve an import for anything other that Javascript. Under the hood, you always have to use an AJAX call (fetch / XHR) and parse the result, even if your build toolchain abstracts that away.Pl
so that we don't forget as we get excited, what transpilers do is simply inline the json content in a constant in the output file, because in the world of javascript, that is really the only safe way (besides ajaxing which is a different story)Orazio
S
173

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.

Stir answered 4/10, 2016 at 14:46 Comment(8)
This doesn't actually answer the question. You can't simply convert your package.json into package.js for example. There are times when you want to truly import JSON not JS.Gainsborough
Not a solution at all, you are exporting a javascript object which happens to have the same syntax as JSON.Important
Updated the issue text; attempt to avoid further semantical debates.Stir
I added a "postbuild": "node myscript.js" step in my package.json file that uses replace-in-file to do this for me. myscript.js ­ const replace = require('replace-in-file'); const options = { files: '_demo/typedocs/navexReact.td.js', from: /{/, to: 'export default {', }; const convertJsonOutputToJsModule = async () => { try { const changes = await replace(options) console.log('Converted json to module in files:', changes.join(', ')); } catch (error) { console.error('Error occurred:', error); } } convertJsonOutputToJsModule() Oxygen
"convert it to JS" is not a solution for how to import a JSON file. That's not JSON file anymore. This is a #1 google result for how to import JSON, and the main answer is to not import JSON.Hodess
Having config in .js file is more convenient, because you can have comments inside. JSON file does not support this.Plumley
The syntax in the proposal has changed.Octangular
At least me was helped a lot with this. I used the assert { type: json` };` style only to learn that FF does not support it yet. I have control of everything so making a .js file out of my .json file is not a problem. My code is nearly untouched - so I can live with it happily, thanks!Wateriness
K
95

Unfortunately, ES6/ES2015 doesn't support loading JSON via the module import syntax. But...

There are many ways you can do it. Depending on your needs, you can either look into how to read files in JavaScript (window.FileReader could be an option if you're running in the browser) or use some other loaders as described in other questions (assuming you are using NodeJS).

IMO simplest way is probably to just put the JSON as a JS object into an ES6 module and export it. That way, you can just import it where you need it.

Also, worth noting if you're using Webpack, importing of JSON files will work by default (since webpack >= v2.0.0).

import config from '../config.json';
Knesset answered 22/1, 2016 at 12:10 Comment(7)
There's no need to put it in a String. It's called JSON, not JSSN, after all.Bourbon
Also, torazaburo explained in a previously deleted answer: There is no ES6 "module system"; there is an API which is implemented by a particular loader. Any loader can do anything it wants, including supporting the import of JSON files. For instance, a loader might choose to support import foo from './directory as meaning to import directory/index.jsHeist
in fact ES6/ES2015 do support loading JSON via import syntax: import * as data from './example.json';Scent
+1 for the reminder that webpack does it automatically. Careful though, if you have "test: /.js/" webpack will attempt to compile your json file as JavaScript. #fail. To fix it, change it to say "test: /.js$/"Supramolecular
webpack is based on nodejs, isn't it?Orazio
This answer and the comment from @Scent are directly contradictory. Do either of you guys have a link?Bardwell
Ah actually I see there is a slight syntax difference, sorry about that!Bardwell
B
41

If you're using node you can:

const fs = require('fs');

const { config } = JSON.parse(fs.readFileSync('../config.json'));

OR

const evaluation = require('../config.json');
// evaluation will then contain all props, so evaluation.config
// or you could use:
const { config } = require('../config.json');

Else:

// config.js
{
// json object here
}

// script.js

import { config } from '../config.js';

OR

import * from '../config.json'
Beadsman answered 18/1, 2019 at 21:0 Comment(2)
const config = JSON.parse(fs.readFileSync('../config.json')); worked for me. Node is a mess.Toothbrush
I think here const { config } = JSON.parse(fs.readFileSync('../config.json')); missed param 'utf8', so it should look like this: JSON.parse(fs.readFileSync('../package.json', 'utf8')); Clementius
P
32

Thanks to all the people who proposed and implemented JSON modules and Import Assertions. Since Chrome 91, you can import JSON directly, for example:

// test.json
{
    "hello": "world"
}

// Static Import
import json from "./test.json" assert { type: "json" };
console.log(json.hello);

// Dynamic Import
const { default: json } = await import("./test.json", { assert: { type: "json" } });
console.log(json.hello);

// Dynamic Import
import("./test.json", { assert: { type: "json" } })
  .then(module => console.log(module.default.hello));

Note: other browsers may not yet implement this feature at the moment.

Planer answered 30/7, 2021 at 15:4 Comment(1)
This is also flagged as experimental in NodeJS 18 and generates an ExperimentalWarning.Caa
C
30

I'm using babel+browserify and I have a JSON file in a directory ./i18n/locale-en.json with translations namespace (to be used with ngTranslate).

Without having to export anything from the JSON file (which btw is not possible), I could make a default import of its content with this syntax:

import translationsJSON from './i18n/locale-en';
Calista answered 31/1, 2017 at 0:7 Comment(0)
A
27

Depending on your build tooling and the data structure within the JSON file, it may require importing the default.

import { default as config } from '../config.json';

e.g. usage within Next.js

Algesia answered 19/6, 2019 at 13:10 Comment(2)
Added note for TypeScript is to ensure resolveJsonModule is true in you tsconfig.json.Algesia
This is the only solution that worked for me when the JSON is an array (the other solution - import * as data from './example.json' only worked when the JSON is an object)Philippe
Z
27

In a browser with fetch (basically all of them now):

At the moment, we can't import files with a JSON mime type, only files with a JavaScript mime type. It might be a feature added in the future (official discussion).

fetch('./file.json')
  .then(response => response.json())
  .then(obj => console.log(obj))

In Node.js v13.2+:

It currently requires the --experimental-json-modules flag, otherwise it isn't supported by default.

Try running

node --input-type module --experimental-json-modules --eval "import obj from './file.json'; console.log(obj)"

and see the obj content outputted to console.

Zealotry answered 21/3, 2020 at 3:56 Comment(1)
I did the first one in a browser and it workedBasis
T
10

A bit late, but I just stumbled across the same problem while trying to provide analytics for my web app that involved sending app version based on the package.json version.

Configuration is as follows: React + Redux, Webpack 3.5.6

The json-loader isn't doing much since Webpack 2+, so after some fiddling with it, I ended up removing it.

The solution that actually worked for me, was simply using fetch. While this will most probably enforce some code changes to adapt to the async approach, it worked perfectly, especially given the fact that fetch will offer json decoding on the fly.

So here it is:

  fetch('../../package.json')
  .then(resp => resp.json())
  .then((packageJson) => {
    console.log(packageJson.version);
  });

Do keep in mind, that since we're talking about package.json specifically here, the file will not usually come bundled in your production build (or even dev for that matter), so you will have to use the CopyWebpackPlugin to have access to it when using fetch.

Tenaculum answered 26/9, 2017 at 13:11 Comment(3)
Can't. Fetch doesn't support local file ... You might be using polyfill or something.Silden
@Silden Months late reply, but the fetch API most absolutely does support loading from paths without specifying the hostname of the server, as well as loading from relative paths. What you are thinking of is loading from file:/// URLs, which is not what is occurring here.Liebfraumilch
This is a really helpful answer, very simple and worked for me with local filesConsiderable
S
5

Simply do this:

import * as importedConfig from '../config.json';

Then use it like the following:

const config = importedConfig.default;
Saltatorial answered 13/9, 2020 at 14:53 Comment(1)
This does not work natively in browsers, though it may be working in combination with whatever build system you seem to be using (Babel or whatever).Glass
M
5

Adding to the other answers, in Node.js it is possible to use require to read JSON files even inside ES modules. I found this to be especially useful when reading files inside other packages, because it takes advantage of Node's own module resolution strategy to locate the file.

require in an ES module must be first created with createRequire.

Here is a complete example:

import { createRequire } from 'module';

const require = createRequire(import.meta.url);
const packageJson = require('typescript/package.json');
console.log(`You have TypeScript version ${packageJson.version} installed.`);

In a project with TypeScript installed, the code above will read and print the TypeScript version number from package.json.

Magnetograph answered 12/12, 2020 at 9:53 Comment(0)
W
4

For NodeJS v12 and above, --experimental-json-modules would do the trick, without any help from babel.

https://nodejs.org/docs/latest-v14.x/api/esm.html#esm_experimental_json_modules

But it is imported in commonjs form, so import { a, b } from 'c.json' is not yet supported.

But you can do:

import c from 'c.json';
const { a, b } = c;
Waterproof answered 11/11, 2020 at 1:38 Comment(0)
T
4

import data from "./resource.json” is possible in Chrome 91. JSON modules are now supported. This allows developers to statically import JSON instead of relying on the fetch() function which dynamically retrieves it.

https://www.stefanjudis.com/snippets/how-to-import-json-files-in-es-modules/

Torto answered 25/5, 2021 at 16:56 Comment(0)
S
4

A more elegant solution is to use the CommonJS require function

createRequire construct a CommonJS require function so that you can use typical CommonJS features such as reading JSON

import { createRequire } from "module";
const require = createRequire(import.meta.url);
const data = require("./data.json");
Sandwich answered 11/1, 2022 at 20:23 Comment(0)
M
4

import a JSON file in ECMAScript 6

import myJson from './example.json' assert {type: 'json'};
const expample = await import("./example.json", {
  assert: {
    type: "json",
  },
});
Morissa answered 17/1, 2023 at 23:48 Comment(0)
L
4

Dynamic import

const {default: json} = await import("./name.json", {
  assert: {
    type: "json",
  },
});

import

import {default: json} from './name.json' assert {type: 'json'}

CommonJS require

const json = require('./name.json')

Additional Information

If you use Typescript

Set compilerOptions.resolveJsonModule to true in your tsconfig.json

{
  "compilerOptions": {
    "resolveJsonModule": true
  }
}
Lupercalia answered 10/6, 2023 at 15:17 Comment(0)
I
3

importing JSON files are still experimental. It can be supported via the below flag.

--experimental-json-modules

otherwise you can load your JSON file relative to import.meta.url with fs directly:-

import { readFile } from 'fs/promises';
const config = JSON.parse(await readFile(new URL('../config.json', import.meta.url)));

you can also use module.createRequire()

import { createRequire } from 'module';
const require = createRequire(import.meta.url);
const config = require('../config.json');
Imprecation answered 22/1, 2021 at 22:3 Comment(0)
H
2

I used it installing the plugin "babel-plugin-inline-json-import" and then in .balberc add the plugin.

  1. Install plugin

    npm install --save-dev babel-plugin-inline-json-import

  2. Config plugin in babelrc

    "plugin": [ "inline-json-import" ]

And this is the code where I use it

import es from './es.json'
import en from './en.json'

export const dictionary = { es, en }
Himself answered 8/1, 2021 at 22:53 Comment(0)
C
2

I'm using

  • vuejs, version: 2.6.12
  • vuex, version: 3.6.0
  • vuex-i18n, version: 1.13.1.

My solution is:

messages.js:

import Vue from 'vue'
import Vuex from 'vuex';
import vuexI18n from 'vuex-i18n';
import translationsPl from './messages_pl'
import translationsEn from './messages_en'

Vue.use(Vuex);

export const messages = new Vuex.Store();

Vue.use(vuexI18n.plugin, messages);

Vue.i18n.add('en', translationsEn);
Vue.i18n.add('pl', translationsPl);

Vue.i18n.set('pl');

messages_pl.json:

{
    "loadingSpinner.text:"Ładowanie..."
}

messages_en.json:

{
    "loadingSpinner.default.text":"Loading..."
}

majn.js

import {messages} from './i18n/messages'
Vue.use(messages);
Constitutional answered 4/2, 2021 at 14:28 Comment(0)
A
2

let filePath = '../../data/my-file.json'

let arrayImport = await import(filePath, {
  assert: { type: "json" },
});
const inputArray = arrayImport.default 

console.log('result', inputArray)

More information here: v8 - Dynamic import().

Amato answered 7/8, 2022 at 23:35 Comment(2)
Thank you! Didn't know how to apply the assert until finding this.Cocytus
last line correction -> console.log('result: ', inputArray)Cense
M
2

Make sure the type attribute is set to module because we are using the ES6 Modules syntax.

And here is how we would import a JSON file in our index.js file.

import myJson from './example.json' assert {type: 'json'};
Morissa answered 17/1, 2023 at 23:46 Comment(0)
D
1

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.

Option 1: Read and parse JSON files yourself

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)
  )
);

Option 2: Leverage the CommonJS require function to load JSON files

The 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");
Dobby answered 20/1, 2023 at 10:52 Comment(0)
B
0

As said by Azad, the correct answer is to load the file with fs.readFileSync() (or any of the asynchronous variants such as fs.readFile with callback or fs.promises.readFile with promises/await, then parse the JSON with JSON.parse()

const packageJsonRaw = fs.readFileSync('location/to/package.json' ) 
const packageJson = JSON.parse(packageJsonRaw )

Webpack/Babel options are not practical unless you are already using that set up.

Bashaw answered 12/12, 2021 at 19:25 Comment(0)
I
-1

The file structure with the json extension is used to transfer data, the json file data can be retrieved locally by sending a request using the fetch command.

In the following example, the data of the count.json file is received

// count.json

fetch("./count.json") 
.then((response) => { return response.json(); }) 
.then((data) => console.log(data));
Irrefrangible answered 4/3, 2022 at 12:29 Comment(3)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Expostulation
See "Explaining entirely code-based answers". While this might be technically correct, it doesn't explain why it solves the problem or should be the selected answer. We should educate along with helping solve the problem.Foredoom
@theTinMan Thank you for your attention, I will explain this answer. You are right The answers should be educationalIrrefrangible

© 2022 - 2024 — McMap. All rights reserved.