Browsers Now Natively Support JSON Module Imports for Development!
Native JSON modules let browser JavaScript import JSON data directly with import attributes.
This page keeps every demo self-contained by creating JSON files as in-memory Blob URLs with
the required application/json MIME type.
1. Import JSON with an Import Attribute
Code:
const jsonUrl = URL.createObjectURL(
new Blob([
'{"feature":"Native JSON modules","supported":true,"syntax":"with { type: \\"json\\" }"}'
], { type: "application/json" })
);
const module = await import(jsonUrl, {
with: { type: "json" }
});
document.querySelector("[data-result='native']").textContent =
JSON.stringify(module.default, null, 2);
URL.revokeObjectURL(jsonUrl);
Result:
The imported JSON becomes
module.default.
Click the button to import JSON as a native module.
2. Read Imported JSON Like a Normal Module Value
Code:
const jsonUrl = URL.createObjectURL(
new Blob([
'{"bookName":"HTML并不简单","url":"https://www.htmlapi.cn/"}'
], { type: "application/json" })
);
const config = (await import(jsonUrl, {
with: { type: "json" }
})).default;
document.querySelector("[data-result='book-name']").textContent = config.bookName;
document.querySelector("[data-result='book-url']").href = config.url;
document.querySelector("[data-result='book-url']").textContent = config.url;
URL.revokeObjectURL(jsonUrl);
Result:
No manual
fetch() or JSON.parse() step is needed.
bookName
Waiting for import...
3. Import Attributes Require JSON MIME Type
Code:
const jsonUrl = URL.createObjectURL(
new Blob([
'{"contentType":"application/json","works":true}'
], { type: "application/json" })
);
const textUrl = URL.createObjectURL(
new Blob([
'{"contentType":"text/plain","works":false}'
], { type: "text/plain" })
);
try {
const data = (await import(jsonUrl, {
with: { type: "json" }
})).default;
document.querySelector("[data-result='mime-ok']").textContent =
"Imported: " + JSON.stringify(data);
} catch (error) {
document.querySelector("[data-result='mime-ok']").textContent = error.message;
}
try {
await import(textUrl, {
with: { type: "json" }
});
} catch (error) {
document.querySelector("[data-result='mime-bad']").textContent =
"Rejected because MIME is text/plain.";
}
URL.revokeObjectURL(jsonUrl);
URL.revokeObjectURL(textUrl);
Result:
A
.json filename alone is not enough.
application/json:
Waiting...
text/plain: Waiting...
text/plain: Waiting...
4. Imported JSON Module Objects Are Frozen
Code:
const jsonUrl = URL.createObjectURL(
new Blob([
'{"locked":true,"message":"Native JSON module data"}'
], { type: "application/json" })
);
const data = (await import(jsonUrl, {
with: { type: "json" }
})).default;
let mutationResult;
try {
data.locked = false;
mutationResult = "Mutation attempted. Current value: " + data.locked;
} catch (error) {
mutationResult = error.name + ": " + error.message;
}
document.querySelector("[data-result='frozen']").textContent =
"Object.isFrozen(data): " + Object.isFrozen(data) + "\n" + mutationResult;
URL.revokeObjectURL(jsonUrl);
Result:
The browser freezes the parsed JSON module value.
Click the button to test mutation.
5. Large JSON Can Still Be Better with Fetch
Code:
const rows = Array.from({ length: 6 }, (_, index) => ({
id: index + 1,
name: "record-" + String(index + 1).padStart(2, "0"),
loadedAt: new Date().toLocaleTimeString()
}));
const jsonUrl = URL.createObjectURL(
new Blob([JSON.stringify(rows)], { type: "application/json" })
);
const response = await fetch(jsonUrl);
const data = await response.json();
document.querySelector("[data-result='fetch']").textContent =
JSON.stringify(data, null, 2);
URL.revokeObjectURL(jsonUrl);
Result:
For large data, loading later can protect first-screen performance.
Click the button to fetch JSON only when needed.
6. TypeScript Needs resolveJsonModule
Code:
const tsconfig = {
compilerOptions: {
module: "ESNext",
moduleResolution: "Bundler",
resolveJsonModule: true
}
};
document.querySelector("[data-result='tsconfig']").textContent =
JSON.stringify(tsconfig, null, 2);
Result:
This lets TypeScript understand JSON imports.
Click the button to generate the config snippet.
7. Article Ending: Fishing Catch Data as JSON
Code:
const catches = [
{ place: "Huiguo", price: "138 yuan", weightJin: 37, fish: "carp and crucian carp" },
{ place: "Kaixiang", price: "148 yuan / 6 hours", weightJin: 33, fish: "bream" },
{ place: "Liuliu", price: "180 yuan / 6 hours", weightJin: 36, fish: "bream" },
{ place: "Qiangzi Fishing Ground", price: "150 yuan / 6 hours", weightJin: 10, fish: "mixed fish" },
{ place: "Xinsheng", price: "148 yuan / 6 hours", weightJin: 20, fish: "mainly bream" },
{ place: "Futan Fishing Ground", price: "100 yuan / 5 hours", weightJin: 2, fish: "crucian carp pond, dud pond" }
];
document.querySelector("[data-result='catches']").innerHTML = catches.map(item => `
<article class="catch">
<b>${item.place}</b>
<span>${item.price} · ${item.weightJin} jin · ${item.fish}</span>
<div class="meter"><span style="width:${Math.min(item.weightJin / 40 * 100, 100)}%"></span></div>
</article>
`).join("");
Result:
The article’s ending can also be modeled as structured JSON-style data.