使用方法
- 「.env 源文本」默认已写好十行:第一行是井号注释,第二行带 export 前缀,第七行是单引号字面值,第八行是双引号转义值,第九行末尾带行内注释,第十行的引号内藏着一个井号。
- 点「转为JSON」或在文本框里按 Ctrl+Enter(Mac 是 Cmd+Enter)完成解析;在「键名过滤」输入框里按回车同样触发。
- 「JSON 缩进空格数」默认 2,可填 0 到 8 的整数。填 0 输出压缩成一行,适合比较两份配置;填 4 接近多数编辑器保存 .json 的默认宽度。
- 「键名过滤」留空表示全部保留;填入 APP 只输出键名里含这三个字符的键。一个都没命中时会提示当前共有多少个键。
- 「输出顺序」默认按首次出现次序,与 dotenv 的加载顺序一致;也可改按键名升序或降序,方便和另一份配置逐行比对。
- 结果区第一行是统计摘要:总行数、注释行数、空行数、有效键数与重复键覆盖行号;下面是可直接保存的 JSON 原文,「复制结果」复制的就是它。
- 输入框被清空时点「转为JSON」会自动填回示例;本页不联网也不写 localStorage,刷新即恢复默认。
- 键名不合法、找不到等号、引号不闭合、收尾引号后有多余内容,都会给出写明第几行与原因的具体提示,不静默跳过任何一行。
这个环境变量转JSON转换器能解决什么
把 .env 转成 JSON 的需求集中在三类场景。第一类是格式迁移:dotenv 只把变量塞进 process.env,产物仍是平面字符串;要交给前端构建脚本或配置中心,往往需要结构化 JSON。本页输出的值一律是字符串,与 dotenv 的返回值一致,不会把 "8080" 悄悄变成数字,也不会把 "true" 变成布尔值。
第二类是审查别人写的 .env。重复键极其常见——先写 DEBUG=true,后面又写 DEBUG=false,生效的永远是后者;本页在摘要里给出「第几行覆盖第几行」,键名含连字符、以数字开头也会被逐行点名。行内注释的井号前少了空格,会把半句话卷进值里,这类问题同样能在对照表里逐条看明白。
第三类是学习对照。单引号与双引号的差别、行内注释为什么要求 # 前有空白、export 前缀从哪来,这些规则散落在各语言实现里。本页用一张二十行对照表逐条列出,每行结果都由页面自己的解析器现场算出。
边界也要说清:本页只做文本解析与格式转换,不执行命令、不展开值里的变量引用、不判断密钥强度。源文本里有真实密钥时,建议只在本地浏览器里用,不要贴进任何在线服务。
解析规则与变量说明
解析器是一个逐行扫描器,外加一个「是否处于双引号内」的状态。每行先剥掉行首空白;整行以井号开头的行直接丢弃;行首的 export 后跟空白的前缀被剥掉;再按第一个等号切成键名与剩余部分。键名用正则 /^[A-Za-z_][A-Za-z0-9_]*$/ 校验,不合法就报「第 N 行:键名 X 不合法」。
值的部分按首字符分三种状态。双引号开头时进入转义扫描:\n 变真换行、\t 变制表符、\" 变引号、\\ 变反斜杠、\r 变回车,未定义的序列保留反斜杠本身;这一行扫不到收尾引号时,状态保持「在引号内」,继续吃下一行,因此双引号值可以跨行。单引号开头时是字面值:找到下一个单引号即结束,里面的 \n 就是反斜杠加 n 两个字符。两者都不加引号时,剥掉首尾空白,再找到前面带空白的井号,切掉行内注释。
重复键后者胜,这是 dotenv 的既定行为:对象赋值不改变键的既有位置,所以 JSON 里 APP_NAME 仍出现在第一次出现的地方,值却是最后一次写入的 "demo2",摘要会把两次行号都列出来。空行直接跳过;KEY= 这种等号后什么都没有的写法解析成空字符串,不报错,也不是 null。
输出值一律是字符串,这是 .env 的本质:文件里没有类型信息,"8080"、true、1.5 在 dotenv 眼里都只是字符序列,类型的解释权交给读取方。
| 变量 | 含义 | 取值 | 影响 |
|---|---|---|---|
| ind | JSON 缩进空格数 | 0 ~ 8 的整数 | 0 时输出压缩成一行 |
| flt | 键名过滤串 | 任意文本,留空为全部 | 只输出键名包含该串的键 |
| ord | 输出顺序 | keep / asc / desc | 默认保持首次出现顺序 |
| iq | 双引号状态 | true 表示处于引号内 | 为 true 时跨行继续吃下一行 |
| dup | 重复键记录 | 键名与两次行号 | 摘要输出覆盖行号 |
完整示例
默认的十行源文本逐行看:第一行整行是注释;第二行的 export 前缀被剥掉后键名是 APP_NAME;第三行再次写入 APP_NAME,值变成 demo2;PORT 与 DEBUG 是无引号值;EMPTY 等号后为空;LITERAL 用单引号包裹,反斜杠原样保留;ESCAPED 用双引号包裹,反斜杠 n 变成真换行;TRAILING 的井号前有空格,后半段被剥掉;QUOTED_HASH 的井号在引号内,是值的一部分。
# 示例配置:注释行以井号开头 → 注释行,不产生键 export APP_NAME=demo → APP_NAME = "demo" APP_NAME=demo2 → APP_NAME = "demo2"(重复键,后者胜) PORT=8080 → PORT = "8080" DEBUG=true → DEBUG = "true" EMPTY= → EMPTY = "" LITERAL='C:\new\table' → LITERAL = "C:\\new\\table"(单引号不转义) ESCAPED="line1\nline2" → ESCAPED = "line1\nline2"(反斜杠 n 是真换行) TRAILING=value # 这是行内注释 → TRAILING = "value"(井号前有空白,剥离注释) QUOTED_HASH="a#b" → QUOTED_HASH = "a#b"(引号内的井号不是注释)
把「JSON 缩进空格数」改成 0,同样的十行输出成一行紧凑 JSON,键的次序不变;改成 4 则每级缩进多两个空格。把「键名过滤」改成 APP,输出里只剩 APP_NAME 一个键,摘要仍显示解析出的全部八个键,并在末尾追加保留数;改成 ZZ 则一个都不命中,页面提示当前共解析出八个键。把「输出顺序」改成升序,APP_NAME 仍排最前,按码点它本来就小于 PORT。
dotenv 行形对照表
下表列出二十种 .env 行形经过本页解析后的结果,由页面自己的解析器逐条算出,前十二行直接展开,点工具区的「加载更多」看余下八行。报错行给出的是完整错误文案。
| 行形 | 解析结果 | 说明 |
|---|---|---|
| PORT=8080 | PORT → "8080" | 无引号数字仍是字符串 |
| DEBUG=true | DEBUG → "true" | 布尔文本按字符串保留 |
| EMPTY= | EMPTY → "" | 空值是空字符串 |
| TRIMMED= spaced | TRIMMED → "spaced" | 无引号去首尾空白 |
| HASH_IN=a#b | HASH_IN → "a#b" | 井号前无空白算值 |
| HASH_OUT=a #b | HASH_OUT → "a" | 井号前有空白是注释 |
| LIT='C:\new\t' | LIT → "C:\\new\\t" | 单引号内反斜杠保留 |
| ESC="a\nb" | ESC → "a\nb" | 反斜杠n变真换行 |
| ESC2="say \"hi\"" | ESC2 → "say \"hi\"" | 反斜杠引号变引号 |
| TAB="x\ty" | TAB → "x\ty" | 反斜杠t变制表符 |
| export A=1 | A → "1" | export 前缀剥掉 |
| # NOTE=1 | 不产生任何键 | 注释行不产生键 |
第二张表列出双引号值里支持的转义序列,以及单引号内的对应行为。未定义的序列保留反斜杠本身,不会把字符吃掉。
| 写法 | 双引号内 | 单引号内 |
|---|---|---|
| \n | 真换行 | 反斜杠加 n 两个字符 |
| \t | 制表符 | 反斜杠加 t 两个字符 |
| \" | 双引号 | 直接写字面引号即可 |
| \\ | 一个反斜杠 | 两个反斜杠原样保留 |
| \r | 回车 | 反斜杠加 r 两个字符 |
| \x 等未定义序列 | 保留反斜杠加原字符 | 同样原样保留 |
结果边界与错误提示
- 源文本整段为空或只有空白时,提示「.env 源文本这一栏是空的」,不会输出空对象;点「转为JSON」会自动填回示例。
- 键名不合法时提示「第 N 行:键名 X 不合法」,并附合法键名的完整规则;以数字开头、含连字符、含空格的键名都走这条路径。
- 某行找不到等号时提示「第 N 行找不到 = 号」,并把该行原文引出来,避免在几十行里人工数行号。
- 单引号没有闭合时提示「第 N 行:单引号没有闭合」,并说明单引号是字面值、不处理转义也不能跨行。
- 双引号没有闭合时会先尝试跨行继续,直到文件末尾仍不闭合才提示「第 N 行:双引号没有闭合」。
- 收尾引号之后还有既非空白也非井号注释的内容时,提示「第 N 行:引号收尾后还有多余内容」,并把多余部分引出来。
- 重复键不报错,只在摘要里记录覆盖关系;空值解析成空字符串,不会出现 null 或 undefined。
- 本页不做变量展开,值里的 $OTHER 原样输出;导出的 CSV 带字节序标记,Excel 打开不乱码,复制到剪贴板的 JSON 不带字节序标记。
常见问题
为什么 PORT=8080 解析出来是 "8080" 而不是数字?
因为 .env 文件里没有类型信息,dotenv 的既定行为就是把所有值当字符串读。本页忠实还原这一口径:值一律是字符串,"8080" 与 8080 的差别由读取方决定。若确实需要数字,请在读取后用 Number() 自行转换。
单引号和双引号到底差在哪?
单引号是字面值:里面的反斜杠、字母 n、制表符写法都原样保留,写 'C:\new' 得到的就是这六个字符。双引号会处理转义:\n 变真换行、\t 变制表符、\" 变引号。Windows 路径这类不希望被转义的内容,用单引号更稳。
行内注释的井号为什么要求前面有空白?
因为井号本身可以是值的一部分。COLOR=#fff 里的井号紧跟等号、没有前导空白,按规则算值的一部分,解析成 "#fff";若想表达注释,必须写成 COLOR= #fff 这种井号前有空白的形式,值才是空字符串。
重复键为什么后者胜,前面的值会丢吗?
会丢,这是 dotenv 的既定行为:后出现的赋值覆盖先前的值。本页在摘要里给出「第几行覆盖第几行」,键在 JSON 里的位置仍留在首次出现处,因此结构顺序稳定,只有值变化。想保留两个值,请改写成不同的键名。
export 前缀是必须的吗?
不是。export 是 bash 的习惯,写在 .env 里是为了能直接 source 执行。本页解析时会把它剥掉,键名取 export 之后的部分;不写 export 的普通 KEY=VALUE 同样合法。
值里面的 $VAR 会展开吗?
不会。变量展开不是 dotenv 标准的必备行为,各实现口径也不一致。本页选择不展开,值里的 $OTHER 原样出现在 JSON 中,避免出现「展开了一半」的难查故障。
双引号值真的可以跨行吗?
可以,但仅限双引号值。扫到行尾仍未闭合时,解析器保持「在引号内」的状态继续吃下一行,行间的换行符会成为值的一部分。单引号值不支持跨行,遇到行尾即报「单引号没有闭合」。
解析出的 JSON 能直接 JSON.parse 读回吗?
能。输出是标准 JSON 对象,键名都已通过合法键名校验,值全部是字符串,不含注释与尾随逗号。复制结果或导出后可直接被任何 JSON 解析器读取;本页的 JSON 输出与复制都不带 BOM。
相关工具
- CSV转JSON转换器:把表格数据按行列解析成 JSON 数组。
- YAML转JSON转换器:处理带缩进与类型的配置格式。
- XML转JSON转换器:把标签树转成嵌套结构。
- JSON转CSV转换器:反向把对象数组摊成表格。
- JSON转XML转换器:把结构化数据写成标签形式。