JavaScript Import Attributes: The Modern Way to Import JSON Safely
A production-focused guide to JavaScript import attributes, including with { type: "json" }, dynamic imports, MIME-type safety, Node.js behavior, bundler migration, and interview explanations.
JS Interview Prep Editorial Team
Author
6/21/2026
Published
2 views
Views
JavaScript Import Attributes: The Modern Way to Import JSON Safely
JavaScript modules started with a simple assumption: import statements load JavaScript. Real applications quickly needed more. Teams import JSON configuration, localization dictionaries, generated metadata, design tokens, and sometimes CSS module objects. Import attributes give the runtime extra information about what kind of module is expected.
The most common example is importing JSON with with { type: "json" }. The syntax looks small, but the reason behind it is important: the runtime should not accidentally execute a file as JavaScript when the developer expected inert JSON data.
Why this topic is new and searchable
Many developers are still migrating from older import assertion syntax using assert to the current import attributes syntax using with. They also search for why JSON imports fail in browsers or Node.js, why MIME type checking matters, and when they should use fetch instead of import.
- import JSON with type json JavaScript
- import attributes versus import assertions
- dynamic import with attributes example
- why JSON module import requires with type json
The basic syntax
The attribute appears after the module specifier. For JSON modules, type: "json" tells the runtime that the import should be validated as JSON.
import packageInfo from './package.json' with { type: 'json' };
console.log(packageInfo.name);Dynamic import supports attributes too. The attributes are passed in the second argument under the with property.
const locale = await import('./locales/en.json', {
with: { type: 'json' },
});
console.log(locale.default.homepageTitle);The security reason behind type: json
A URL ending in .json is not enough. Browsers and runtimes rely on response metadata such as Content-Type, not just file extensions. If a server returns a file with a JavaScript MIME type, a plain import could treat it as executable code. Import attributes let the developer require the expected module type.
This is especially relevant for remote modules, CDNs, generated files, and systems where content type can be misconfigured. The attribute turns an assumption into a validation rule.
When to use import attributes and when to use fetch
Use import attributes for data that behaves like a module dependency. Examples include static configuration, version metadata, build-time dictionaries, and files that should be cached as modules for the lifetime of the environment.
- Use import attributes for static JSON bundled with your app.
- Use fetch for data that changes during runtime.
- Use fetch when the request depends on user state, cookies, headers, or query parameters.
- Use import attributes when module caching is a feature, not a problem.
// Good for static data
import countries from './countries.json' with { type: 'json' };
// Better for runtime data
const userCredits = await fetch('/api/me/credits').then((res) => res.json());Migration from assert to with
Older examples often use import assertions with the assert keyword. That syntax has been replaced by import attributes using with. If you are maintaining an older codebase, search for JSON imports and update examples, tests, documentation, and lint rules together.
// Older pattern you may still see
import data from './data.json' assert { type: 'json' };
// Current import attributes pattern
import data from './data.json' with { type: 'json' };The safest migration is runtime-aware. Check your target browsers, Node.js version, bundler, test runner, and TypeScript parser settings before changing every file at once.
Production checklist
- Keep JSON module imports for static data only.
- Use fetch for user-specific or frequently changing data.
- Make sure your bundler and test runner parse import attributes.
- Do not mix assert and with syntax in the same codebase.
- Document why a JSON import is static so future developers do not turn runtime data into a module dependency.
- Add a small compatibility test in CI if you publish a library.
Interview explanation
A strong answer: import attributes tell the runtime how a non-JavaScript module should be loaded and validated. For JSON, with { type: "json" } ensures the imported module is treated as JSON and fails if the response or file does not match the expected type.
Also mention the trade-off: module imports are cached as module dependencies, so they are not a replacement for fetching live API data.
Quick FAQ
Do I need import attributes for every JSON file?
For standards-based JSON module imports, yes, use with { type: "json" }. Some bundlers may support shortcuts, but portable code should use the standard syntax when the runtime requires it.
Why not just fetch the JSON file?
Fetch is better for runtime data. Import attributes are better for static module-like data that should be part of the dependency graph.
Is assert still valid?
The modern syntax is import attributes with the with keyword. Older assert examples should be treated as migration candidates.
