TOML转JSON转换器

把 TOML v1.0.0 文档解析成 JSON:整数按 signed 64 位范围校验,超界即非法;TOML 有四类日期时间而 JSON 没有日期类型,一律退化为字符串;字面串不转义、多行基本串会裁掉起始换行、表数组与内联表各有规则。页面带行号提示、缩进选择与下载,全部在本机完成。

示例里有三处值得注意:9223372036854775807 与 -9223372036854775808 是 signed 64 位的两端,本页按原样输出、不用双精度读;四个日期时间字段转换后全是 JSON 字符串;inf 与 nan 在 JSON 里没有对应数字字面量,本页按字符串输出。

输入框默认写好一份覆盖常用语法的示例,页面打开即自动转换一次;改完按 Ctrl+Enter(Mac 是 Cmd+Enter)重新转换。JSON 下载不带字节序标记,可直接被其它程序读取;文本与结果都不离开本机。

使用方法

  1. 「TOML 输入」默认写好一份示例,页面打开就自动转换一次,不用先点按钮。改内容、换缩进或换键顺序都会立刻重算。
  2. 「缩进」默认 2 个空格,可切到 4 个空格、制表符或紧凑模式。紧凑模式不换行也不缩进,适合把结果嵌进单行字段。
  3. 「键顺序」默认按文档里出现的顺序输出,与 TOML 书写顺序一致;切成按字母排序后,嵌套对象内部的键也会一起排,便于两份配置做文本比对。
  4. 输入框里按 Ctrl+Enter(Mac 是 Cmd+Enter)执行转换,直接按 Enter 会换行,不会误触发。
  5. 转换失败时错误区给出具体行号与原因,例如「第 12 行:整数 9223372036854775808 超出 signed 64 位范围」或「第 20 行:表 database 被重复定义」,不会只写「解析失败」。
  6. 「复制 JSON」复制输出区全文;「下载 JSON」存成 .json 文件,按规范不带字节序标记,可直接被其它程序读取。
  7. 「清空输入」把输入框清空,此时转换会提示请填写内容;「填入示例」把示例写回去,方便从头试。
  8. 输出区下方一行统计显示顶层键数、数组元素总数与输出字节数,用来快速判断解析出来的规模是否符合预期。

TOML转JSON转换器能解决什么

TOML 与 JSON 都是配置格式,但类型系统并不重合:TOML 有日期时间、有 64 位整数、有字面串;JSON 只有对象、数组、字符串、数字、布尔与 null。这一页做的是在有损的地方明确标出损失,而不是悄悄丢掉。

第一类是把手写配置接到只认 JSON 的管道上。Rust 的 Cargo.toml、Python 的 pyproject.toml 常要喂给只吃 JSON 的工具,转换后能直接读。1.0.0 版的表数组 [[products]] 会变成 JSON 数组,内联表 geo 变成嵌套对象,点分键 servers.alpha 等价于两层嵌套。

第二类是核对 64 位整数。TOML 规定整数必须是 signed 64 位,范围 [-9223372036854775808, 9223372036854775807];而 ECMA-404 规定的 JSON 数字只是 IEEE754 双精度,既没有整数类型也没有 64 位保证。9223372036854775807 写进 JSON 后文本不变,但按双精度读取会变成 9223372036854775808。本页按原文输出这个数,并在正文说明读取端会丢精度。

第三类是排掉日期时间的坑。TOML 有四类:带偏移的日期时间(RFC 3339)、本地日期时间、本地日期、本地时间。JSON 一个都没有,所以一律退化为字符串,类型信息留在字符串内容里。反过来从 JSON 回 TOML 时,这些字段不会自动变回日期,需要另加类型标注。

还有一类边界:注释在 TOML 里是语法的一部分,JSON 没有注释,转换时静态丢弃,不会转成某个键。字面串 '…' 里的反斜杠是字面量,转成 JSON 字符串时才按 JSON 规则重新转义,两个方向的规则不同,不能简单套用。

转换规则与类型对照

整页分两步:先按 TOML v1.0.0 解析成内存里的对象,再序列化成 JSON。解析阶段一行一行走,遇到 [表名] 切换当前表,遇到 [[表名]] 往表数组里追加一张新表,遇到 键 = 值 写进当前表。TOML 顶层恒为一张表,所以 JSON 顶层恒为对象,不会出现数组或标量。

整数按 signed 64 位校验,不是按双精度。范围是 [-9223372036854775808, 9223372036854775807],写 9223372036854775808 就是非法 TOML。不同语言的解码器行为并不一致:规范规定超界即错,但实测 Python 3.13 的 tomllib 会放行 9223372036854775808,Go 与 Rust 的解码器才报错。本页按规范判非法,并给出行号。

TOMLJSON说明
字符串(基本串 / 字面串 / 多行)字符串按 JSON 规则重新转义
整数数字signed 64 位,超 2⁵³ 会丢精度
浮点数(含 inf / nan)数字或字符串inf 与 nan 无对应字面量,按字符串输出
布尔true / false一一对应
带偏移的日期时间字符串RFC 3339 文本原样保留
本地日期时间 / 本地日期 / 本地时间字符串无 JSON 对应类型,原样保留
数组(可嵌套、可多行)数组尾逗号合法,转换后消失
内联表对象不可换行,定义后不可追加键
表 / 表数组对象 / 数组同一张表不可重复定义
注释 #(丢弃)JSON 无注释,不转成任何键

基本串的合法转义只有 9 个。\b \t \n \f \r \" \\ \uXXXX \UXXXXXXXX,写 \x 或 \d 都是非法的。字面串 '…' 完全不做转义,反斜杠就是反斜杠;多行字面串 '''…''' 同理。多行基本串 """…""" 会裁掉紧跟开头定界符后的第一个换行,行尾的反斜杠则把后续空白与换行一起吃掉。

裸键字符集是 [A-Za-z0-9_-],点分键等价嵌套。a.b.c = 1 与 [a.b] 下写 c = 1 等价,都是三层嵌套。键名需要其它字符时必须加引号,"127.0.0.1" 这样的键只有加引号才不会被当成点分键。同一行写两个键值对是非法的,规范与实现一致报错。

舍入与精度只影响显示。整数在 2⁵³ 以内按原样输出,超出后按 TOML 原文输出并提示读取端会丢精度;浮点按双精度转文本,能短则短。缩进与键顺序只改变排版,不改变语义,两份输出用同一解析器读回来应当等价。

完整示例(内容仅作演示)

输入框默认示例里挑三行看。第一行 big = 9223372036854775807,这是 signed 64 位的上界,本页判合法并原样输出。第二行 dob = 1979-05-27T07:32:00Z 是带偏移的日期时间,转换后变成字符串 "1979-05-27T07:32:00Z",Z 表示零偏移。第三行 geo = { lat = 36.07, lon = 120.38 } 是内联表,转换后是嵌套对象。

# TOML
[owner.address]
geo = { lat = 36.07, lon = 120.38 }

# 转换后的 JSON(缩进 2)
{
  "owner": {
    "address": {
      "geo": { "lat": 36.07, "lon": 120.38 }
    }
  }
}

再看日期时间一组:dob = 1979-05-27T07:32:00Z 是带偏移的日期时间,localdt = 1979-05-27T07:32:00 是本地日期时间,locald = 1979-05-27 是本地日期,localt = 07:32:00 是本地时间。四行转换后分别是 "1979-05-27T07:32:00Z"、"1979-05-27T07:32:00"、"1979-05-27"、"07:32:00",全是 JSON 字符串,偏移信息只留在第一行的文本里。

反向核对:把输出区的内容存成 .json,再用任意 JSON 解析器读回来,对象结构与左侧 TOML 的表结构应当一一对应。表数组 [[products]] 变成含两个元素的数组,每个元素有 name 与 sku 或 name 与 color,缺的键不会补默认值,这与 TOML 的行为一致。

TOML与JSON类型对照表

下表按 TOML 值的种类列出转换后的 JSON 形态与常见陷阱。左边是写法,中间是结果,右边是容易出错的地方。

TOML 写法JSON 结果陷阱
a = 1"a": 1双精度可精确表示
a = 9223372036854775807"a": 9223372036854775807文本不变,双精度读回会变 808
a = 9223372036854775808报错超出 signed 64 位,非法 TOML
a = 0xDEADBEEF"a": 3735928559十六进制转十进制
a = 1_000_000"a": 1000000下划线只作分组,不输出
a = inf"a": "inf"JSON 无对应数字字面量
a = nan"a": "nan"同上
a = 'C:\no\escape'"a": "C:\\no\\escape"字面串不转义,JSON 侧要转
a = """x\ny""""a": "x\ny"多行串里的转义仍生效
a = [1, 2, 3,]"a": [1, 2, 3]尾逗号合法,转换后消失
[a.b]"a": { "b": {} }点分等价两层嵌套
[[a]]"a": [{}]表数组,重复出现即追加
# 注释(无对应键)静态丢弃

读这张表抓两个锚点:9223372036854775807 那一行是唯一「文本不变但读回会变」的情况,凡是可能被双精度读取的下游都要小心;0xDEADBEEF 那一行说明十六进制在 TOML 里合法,转到 JSON 后必须是十进制 3735928559,保留 0x 前缀就是错的。

结果边界、舍入与适用说明

常见问题

为什么 9223372036854775807 转过去还是它,读回来却变了?

因为 TOML 的整数是 signed 64 位,而 JSON 的数字只是 IEEE754 双精度。9223372036854775807 写进 JSON 文件后文本不变,但任何按双精度解析的语言读它都会得到 9223372036854775808。要无损传递只能把它当字符串,或者换用支持大整数的 JSON 扩展。

9223372036854775808 到底算不算错?

按规范算。TOML v1.0.0 规定整数必须是 signed 64 位,上界 9223372036854775807,写 808 就是非法文档。但各语言解码器行为不同:Python 3.13 的 tomllib 会放行,Go 与 Rust 的解码器报错。本页按规范判非法,避免把问题留给下游。

日期时间为什么变成字符串,不能保留成日期吗?

因为 JSON 没有日期类型。ECMA-404 只定义了对象、数组、字符串、数字、布尔与 null 六种,日期时间只能编码成字符串。TOML 有四类日期时间,本页把它们原样转成字符串,类型差异留在文本内容里,下游要还原需要另加约定。

inf 和 nan 怎么处理?

JSON 没有对应的数字字面量,本页把它们转成字符串 "inf" 与 "nan"。这样至少不会静默变成 null 或 0。如果下游要求数字,需要自己约定 sentinel 值,例如用极大数代表 inf。

注释会丢失吗?

会,而且必须丢。TOML 的注释是语法的一部分,JSON 根本没有注释语法,任何「保留注释」的做法都得靠非标准扩展键。本页在转换时静态丢弃注释,不生成任何占位键。

字面串和基本串的转义规则为什么不一样?

基本串 "…" 支持九种转义:\b \t \n \f \r \" \\ \uXXXX \UXXXXXXXX。字面串 '…' 完全不做转义,反斜杠就是反斜杠,适合写 Windows 路径与正则。多行基本串 """…""" 里转义仍生效,还会裁掉开头定界符后的第一个换行;多行字面串 '''…''' 则连换行都不动。

表数组和内联表有什么区别?

表数组 [[x]] 可以在文档里反复出现,每次往数组里追加一张新表,适合表示记录列表。内联表 { a = 1, b = 2 } 必须写在一行内,定义之后不能再往里加键。两者转成 JSON 分别是数组与对象,结构不同不能互换。

输入的内容会上传到服务器吗?

不会。解析与序列化都在本页的 JavaScript 里完成,没有发起任何网络请求,刷新页面后输入即恢复默认示例。

相关工具