Skip to content

JSON 导入断言类型缺失错误解决方案

问题描述

当在 Node.js 中尝试导入 JSON 文件时,可能会遇到如下错误:

javascript
TypeError [ERR_IMPORT_ASSERTION_TYPE_MISSING]:
  Module "file:///Users/xxxxx/code/projects/xxxxx/dist/server/data/countries.json" 
  needs an import assertion of type "json"

此错误通常发生在 Node.js 17 及以上版本中,当使用 ES 模块语法导入 JSON 文件但未提供必要的类型断言时。

解决方案

方案一:使用 import 断言(推荐)

从 Node.js 17.1.0+ 开始,可以使用 with 关键字进行类型断言:

javascript
import countryTable from "./data/countries.json" with { type: "json" };

TIP

with 是新的标准语法,而 assert 关键字在较新版本中已被弃用,但可能仍为兼容性保留。

方案二:使用 createRequire 方法

对于不支持 import 断言的环境,可以使用 Node.js 的 module.createRequire()

javascript
import { createRequire } from 'node:module';

const require = createRequire(import.meta.url);
const countryTable = require('./data/countries.json');

这种方法适用于 Node.js v12.2.0+ 版本,且不需要启用任何实验性功能。

方案三:手动读取和解析 JSON 文件

如果不希望使用任何实验性功能,可以手动读取和解析 JSON 文件:

javascript
import { readFile } from 'fs/promises';

const loadJSON = async (path) => {
  const data = await readFile(new URL(path, import.meta.url));
  return JSON.parse(data);
};

// 使用方式
const countryTable = await loadJSON('./data/countries.json');

同步版本:

javascript
import { readFileSync } from 'fs';

const loadJSONSync = (path) => {
  return JSON.parse(readFileSync(new URL(path, import.meta.url), 'utf8'));
};

// 使用方式
const countryTable = loadJSONSync('./data/countries.json');

方案四:使用 CommonJS 语法

如果项目配置允许,可以将文件扩展名改为 .cjs 并使用 CommonJS 语法:

javascript
// 将文件重命名为 countries.cjs
const countryTable = require('./data/countries.cjs');

环境配置

Node.js 版本兼容性

不同 Node.js 版本对 JSON 导入的支持:

Node.js 版本支持情况
< 17.0.0需要使用 --experimental-json-modules 标志
17.0.0-17.5.0需要 import 断言
17.5.0+支持 with { type: "json" } 语法
18.0.0+稳定支持 import 断言

启动参数配置

如果必须使用较旧的 Node.js 版本,可以通过命令行标志启用实验性 JSON 模块支持:

bash
node --experimental-json-modules your-script.js

或者在 package.json 中配置:

json
{
  "scripts": {
    "start": "node --experimental-json-modules --no-warnings server/server.js"
  }
}

常见问题解决

ESLint 错误处理

如果遇到 ESLint 不支持 import 断言语法的问题,可以使用以下方法:

  1. 更新 ESLint 和相关插件到最新版本
  2. 暂时禁用相关规则:
javascript
// eslint-disable-next-line import/assertions
import data from './data.json' with { type: 'json' };
  1. 使用文件读取方法替代 import 断言

TypeScript 配置

在 TypeScript 项目中,需要确保 tsconfig.json 配置正确:

json
{
  "compilerOptions": {
    "module": "ESNext",
    "moduleResolution": "node",
    "resolveJsonModule": true
  }
}

最佳实践

  1. 版本兼容性:根据项目使用的 Node.js 版本选择合适的解决方案
  2. 代码可读性:优先使用标准的 with 语法,提高代码可读性
  3. 错误处理:在使用文件读取方法时,添加适当的错误处理机制
  4. 性能考虑:对于频繁读取的 JSON 文件,考虑缓存解析结果

WARNING

使用实验性功能时,请注意这些功能可能在未来的 Node.js 版本中发生变化或移除。

通过上述方法,您可以有效地解决 ERR_IMPORT_ASSERTION_TYPE_MISSING 错误,并根据项目需求选择最适合的 JSON 文件导入方式。