运行时包管理器打包器测试运行器代码检查格式化指南参考博客反馈

JSON5

通过运行时 API 和打包工具集成,使用 Bun 内置对 JSON5 文件的支持

在 Bun 中,JSON5 与 JSON、TOML 和 YAML 一样,是一等公民。你可以:

  • 使用 Bun.JSON5.parse 和 Bun.JSON5.stringify 解析和字符串化 JSON5
  • 在运行时将 JSON5 文件作为模块 import 和 require(包括热重载和监视模式支持)
  • 在前端应用中使用 Bun 的打包工具 import 和 require JSON5 文件

兼容性

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,
  },
}

默认导入

app.ts
import config from "./config.json5";

console.log(config.database.host); // "localhost"
console.log(config.features.auth); // true

命名导入

可以将顶层属性作为命名导入进行解构:

app.ts
import { database, features } from "./config.json5";

console.log(database.host); // "localhost"
console.log(features.rateLimit); // true

CommonJS

也可以在 CommonJS 中使用 require 导入 JSON5 文件:

app.ts
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,
  },
}
server.ts
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");