JSON5
通过运行时 API 和打包工具集成,使用 Bun 内置对 JSON5 文件的支持
在 Bun 中,JSON5 与 JSON、TOML 和 YAML 一样,是一等公民。你可以:
- 使用
Bun.JSON5.parse和Bun.JSON5.stringify解析和字符串化 JSON5 - 在运行时将 JSON5 文件作为模块
import和require(包括热重载和监视模式支持) - 在前端应用中使用 Bun 的打包工具
import和requireJSON5 文件
兼容性
Bun 的 JSON5 解析器使用 Rust 编写,并通过了 官方 JSON5 测试套件中的 100% 测试。翻译后的测试套件列出了每个测试用例。
运行时 API
Bun.JSON5.parse()
将 JSON5 字符串解析为 JavaScript 值。
TypeScript
import { JSON5 } from "bun";
const data = JSON5.parse(`{
// JSON5 支持注释
name: 'my-app',
version: '1.0.0',
debug: true,
// 允许尾随逗号
tags: ['web', 'api',],
}`);
console.log(data);
// {
// name: "my-app",
// version: "1.0.0",
// debug: true,
// tags: ["web", "api"]
// }
支持的 JSON5 特性
JSON5 是基于 ECMAScript 5.1 语法的 JSON 超集。它支持:
- 注释:单行(
//)和多行(/* */) - 尾随逗号:对象和数组中
- 未加引号的键:任何有效的 ECMAScript 5.1 标识符
- 单引号字符串:除了双引号字符串之外
- 多行字符串:使用反斜杠进行换行延续
- 十六进制数:
0xFF - 前导和尾随小数点:
.5和5. - Infinity 和 NaN:正数和负数
- 显式加号:
+42
TypeScript
const data = JSON5.parse(`{
// 未加引号的键
unquoted: 'keys work',
// 单引号和双引号
single: 'single-quoted',
double: "double-quoted",
// 尾随逗号
trailing: 'comma',
// 特殊数字
hex: 0xDEADbeef,
half: .5,
to: Infinity,
nan: NaN,
// 多行字符串
multiline: 'line 1 \
line 2',
}`);
错误处理
如果输入不是有效的 JSON5,Bun.JSON5.parse() 会抛出 SyntaxError:
TypeScript
try {
JSON5.parse("{invalid}");
} catch (error) {
console.error("解析 JSON5 失败:", error.message);
}
Bun.JSON5.stringify()
将 JavaScript 值序列化为 JSON5 字符串。
TypeScript
import { JSON5 } from "bun";
const str = JSON5.stringify({ name: "my-app", version: "1.0.0" });
console.log(str);
// {name:'my-app',version:'1.0.0'}
美化输出
传入 space 参数来格式化输出并缩进:
TypeScript
const pretty = JSON5.stringify(
{
name: "my-app",
debug: true,
tags: ["web", "api"],
},
null,
2,
);
console.log(pretty);
// {
// name: 'my-app',
// debug: true,
// tags: [
// 'web',
// 'api',
// ],
// }
space 参数可以是数字(空格数),也可以是字符串(用作每一层的缩进字符串):
TypeScript
// 使用制表符缩进
JSON5.stringify(data, null, "\t");
特殊值
与 JSON.stringify 不同,JSON5.stringify 会保留特殊数值:
TypeScript
JSON5.stringify({ inf: Infinity, ninf: -Infinity, nan: NaN });
// {inf:Infinity,ninf:-Infinity,nan:NaN}
模块导入
ES 模块
可以直接将 JSON5 文件作为 ES 模块导入:
config.json5
{
// 数据库配置
database: {
host: "localhost",
port: 5432,
name: "myapp",
},
features: {
auth: true,
rateLimit: true,
analytics: false,
},
}
默认导入
import config from "./config.json5";
console.log(config.database.host); // "localhost"
console.log(config.features.auth); // true
命名导入
可以将顶层属性作为命名导入进行解构:
import { database, features } from "./config.json5";
console.log(database.host); // "localhost"
console.log(features.rateLimit); // true
CommonJS
也可以在 CommonJS 中使用 require 导入 JSON5 文件:
const config = require("./config.json5");
console.log(config.database.name); // "myapp"
// 解构也支持
const { database, features } = require("./config.json5");
JSON5 热重载
当你使用 bun --hot 运行应用程序时,Bun 会在 JSON5 文件发生更改时重新加载它们:
config.json5
{
server: {
port: 3000,
host: "localhost",
},
features: {
debug: true,
verbose: false,
},
}
import { server, features } from "./config.json5";
Bun.serve({
port: server.port,
hostname: server.host,
fetch(req) {
if (features.verbose) {
console.log(`${req.method} ${req.url}`);
}
return new Response("Hello World");
},
});
使用热重载启动:
terminal
bun --hot server.ts
打包工具集成
使用 Bun 打包时,打包工具会在构建时解析导入的 JSON5 文件,并将它们作为 JavaScript 模块包含在内:
terminal
bun build app.ts --outdir=dist
在构建时解析意味着:
- 生产环境中无需承担运行时 JSON5 解析开销
- 更小的打包体积
- 对未使用的属性进行摇树优化(命名导入)
动态导入
你可以动态导入 JSON5 文件:
TypeScript
const { default: config } = await import("./config.json5");