Skip to content


Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?


Failed to load latest commit information.
Latest commit message
Commit time

JSON modules

Champions: Sven Sauleau (@xtuc), Daniel Ehrenberg (@littledan), Myles Borins (@MylesBorins), and Dan Clark (@dandclark)

Status: Stage 3.

Please leave any feedback you have in the issues!


The JSON modules proposal builds on the import assertions proposal to add the ability to import a JSON module in a common way across JavaScript environments.

Developers will then be able to import a JSON module as follows:

import json from "./foo.json" assert { type: "json" };
import("foo.json", { assert: { type: "json" } });

Note: this proposal was originally part of the import assertions proposal, but it was resolved during the July 2020 meeting to split it out into a separate proposal.


Standards-track JSON ES modules were proposed to allow JavaScript modules to easily import JSON data files, similarly to how they are supported in many nonstandard JavaScript module systems. This idea quickly got broad support from web developers and browsers, and was merged into HTML, with an implementation for V8/Chromium created by Microsoft.

However, in an issue, Ryosuke Niwa (Apple) and Anne van Kesteren (Mozilla) proposed that security would be improved if some syntactic marker were required when importing JSON modules and similar module types which cannot execute code, to prevent a scenario where the responding server unexpectedly provides a different MIME type, causing code to be unexpectedly executed. The solution was to somehow indicate that a module was JSON, or in general, not to be executed, somewhere in addition to the MIME type. Import assertions provide a mechanism for doing so, allowing us to reintroduce JSON modules.

Rather than granting hosts free reign to implement JSON modules independently, specifying them in TC39 guarantees that they will behave consistently across all ECMA262-compliant hosts.

Proposed semantics and interoperability

If a module import has an assertion with key type and value json, the host is required to either fail the import, or treat it as a JSON module. Specifically this means that the content of the module is parsed as JSON and the resulting JSON object is the default export of the module (which has no named exports).

Each JavaScript host is expected to provide a secondary way of checking whether a module is a JSON module. For example, on the Web, the MIME type would be checked to be a JSON MIME type. In "local" desktop/server/embedded environments, the file extension may be checked (possibly after symlinks are followed). The type: "json" is indicated at the import site, rather than only through that other mechanism in order to prevent the privilege escalation issue noted in the opening section.

All of the import statements in the module graph that address the same JSON module will evaluate to the same mutable object as discussed in #54.

Nevertheless, the interpretation of module loads with no assertions remains host/implementation-defined, so it is valid to implement JSON modules without requiring assert { type: "json" }. It's just that assert { type: "json" } must be supported everywhere. For example, it will be up to Node.js, not TC39, to decide whether import assertions are required or optional for JSON modules.

Further assertions and module types beyond json modules could be added in future TC39 proposals as well as by hosts. HTML and CSS modules are also under consideration, and these may use similar explicit type syntax when imported.


How would this proposal work with caching?

The determination of whether the type assertion is part of the module cache key is left up to hosts (as it is for all import assertions). However, hosts are required to interpret the module in the same way (or produce an error), regardless of the assertion.

Why don't JSON modules support named exports?

"Named exports" for each top-level property of the parsed JSON value were considered in earlier HTML efforts towards JSON modules. On one hand, named exports are implemented by certain JavaScript tooling, and some developers find them to be more ergonomic/friendly to certain forms of tree shaking. However, they are not selected in this proposal because:

  • They are not fully general: not all JSON documents are objects, and not all object property keys are JavaScript identifiers that can be bound as named imports.
  • It makes sense to think of a JSON document as conceptually "a single thing" rather than several things that happen to be side-by-side in a file.