diff --git a/doc/api/cli.md b/doc/api/cli.md
index 70cb69cd54a451..449aff30cbfa0e 100644
--- a/doc/api/cli.md
+++ b/doc/api/cli.md
@@ -222,13 +222,6 @@ added:
Enable experimental `import.meta.resolve()` support.
-### `--experimental-json-modules`
-
-
-Enable experimental JSON support for the ES Module loader.
-
### `--experimental-loader=module`
-```js
-import { readFile } from 'fs/promises';
-const json = JSON.parse(await readFile(new URL('./dat.json', import.meta.url)));
-```
-
-Alterantively `module.createRequire()` can be used.
-
#### No Native Module Loading
Native modules are not currently supported with ES module imports.
@@ -471,35 +459,35 @@ separate cache.
## JSON modules
+
> Stability: 1 - Experimental
-Currently importing JSON modules are only supported in the `commonjs` mode
-and are loaded using the CJS loader. [WHATWG JSON modules specification][] are
-still being standardized, and are experimentally supported by including the
-additional flag `--experimental-json-modules` when running Node.js.
-
-When the `--experimental-json-modules` flag is included, both the
-`commonjs` and `module` mode use the new experimental JSON
-loader. The imported JSON only exposes a `default`. There is no
+The imported JSON only exposes a `default` export. There is no
support for named exports. A cache entry is created in the CommonJS
cache to avoid duplication. The same object is returned in
CommonJS if the JSON module has already been imported from the
same path.
-Assuming an `index.mjs` with
-
-
-```js
+```js esm
import packageConfig from './package.json';
+const { version, name } = packageConfig;
+
+console.log(version);
```
-The `--experimental-json-modules` flag is needed for the module
-to work.
+```js cjs
+(async () => {
+ const { default: { version, name } } = await import('./package.json');
-```bash
-node index.mjs # fails
-node --experimental-json-modules index.mjs # works
+ console.log(version);
+})().catch(console.error);
```
diff --git a/lib/internal/modules/esm/get_format.js b/lib/internal/modules/esm/get_format.js
index f02bb5cde70772..5afff8ac56a338 100644
--- a/lib/internal/modules/esm/get_format.js
+++ b/lib/internal/modules/esm/get_format.js
@@ -6,7 +6,6 @@ const {
const { extname } = require('path');
const { getOptionValue } = require('internal/options');
-const experimentalJsonModules = getOptionValue('--experimental-json-modules');
const experimentalSpecifierResolution =
getOptionValue('--experimental-specifier-resolution');
const experimentalWasmModules = getOptionValue('--experimental-wasm-modules');
@@ -18,7 +17,8 @@ const extensionFormatMap = {
'__proto__': null,
'.cjs': 'commonjs',
'.js': 'module',
- '.mjs': 'module'
+ '.mjs': 'module',
+ '.json': 'json',
};
const legacyExtensionFormatMap = {
@@ -33,9 +33,6 @@ const legacyExtensionFormatMap = {
if (experimentalWasmModules)
extensionFormatMap['.wasm'] = legacyExtensionFormatMap['.wasm'] = 'wasm';
-if (experimentalJsonModules)
- extensionFormatMap['.json'] = legacyExtensionFormatMap['.json'] = 'json';
-
function defaultGetFormat(url, context, defaultGetFormatUnused) {
if (StringPrototypeStartsWith(url, 'node:')) {
return { format: 'builtin' };
@@ -49,7 +46,7 @@ function defaultGetFormat(url, context, defaultGetFormatUnused) {
const format = ({
'__proto__': null,
'text/javascript': 'module',
- 'application/json': experimentalJsonModules ? 'json' : null,
+ 'application/json': 'json',
'application/wasm': experimentalWasmModules ? 'wasm' : null
})[mime] || null;
return { format };
diff --git a/src/node_options.cc b/src/node_options.cc
index d292231218f1fc..3b50df159268e3 100644
--- a/src/node_options.cc
+++ b/src/node_options.cc
@@ -303,8 +303,7 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
kAllowedInEnvironment);
AddOption("--experimental-abortcontroller", "",
NoOp{}, kAllowedInEnvironment);
- AddOption("--experimental-json-modules",
- "experimental JSON interop support for the ES Module loader",
+ AddOption("--experimental-json-modules", "",
&EnvironmentOptions::experimental_json_modules,
kAllowedInEnvironment);
AddOption("--experimental-loader",
diff --git a/test/es-module/test-esm-non-js.js b/test/es-module/test-esm-non-js.js
index 3e572809bbdf35..7505a988798a38 100644
--- a/test/es-module/test-esm-non-js.js
+++ b/test/es-module/test-esm-non-js.js
@@ -1,21 +1,15 @@
'use strict';
const common = require('../common');
-const { spawn } = require('child_process');
-const assert = require('assert');
-
-const entry = require.resolve('./test-esm-json.mjs');
+const fixtures = require('../common/fixtures');
-// Verify non-js extensions fail for ESM
-const child = spawn(process.execPath, [entry]);
-
-let stderr = '';
-child.stderr.setEncoding('utf8');
-child.stderr.on('data', (data) => {
- stderr += data;
-});
-child.on('close', common.mustCall((code, signal) => {
- assert.strictEqual(code, 1);
- assert.strictEqual(signal, null);
- assert.ok(stderr.indexOf('ERR_UNKNOWN_FILE_EXTENSION') !== -1);
+const assert = require('assert');
+const { pathToFileURL } = require('url');
+const { Worker } = require('worker_threads');
+
+new Worker(new URL(
+ 'data:text/javascript,' +
+ `import ${JSON.stringify(pathToFileURL(fixtures.path('altdocs.md')))};`
+)).on('error', common.mustCall((err) => {
+ assert.strictEqual(err.code, 'ERR_UNKNOWN_FILE_EXTENSION');
}));