8 种常见配置文件格式怎么选:INI、XML、JSON、YAML、TOML 到 Markdown

整理 8 种常见配置文件格式的特点与取舍,包括 INI、XML、JSON、YAML、TOML、Apache 配置、Protocol Buffers,以及 AI Agent 时代重新受关注的 Markdown。

只要你经常写代码、折腾服务器、改游戏参数,或者维护各种工具链,基本都逃不过配置文件。

很多时候,真正把程序搞炸的不是算法,也不是框架,而是一行不起眼的配置:少了一个空格、多了一个逗号,或者某个值写成了系统不想看到的样子。把常见配置文件格式放在一起看,很自然会回到几个核心问题:

  • 哪些格式更适合人来写
  • 哪些格式更适合机器来读
  • 在 AI Agent 时代,配置文件这件事会不会发生变化

这篇文章就是围绕这个问题做的一次简洁整理。

01 配置文件,本质上是在协调“人”和“机器”

有个说法我觉得很准确:配置文件其实就是人和程序之间签下的一份“行为契约”。

它的价值很明显。你不需要重写业务代码,也不用重新编译,只改几行文本,就能改变网站行为、应用逻辑、部署方式,甚至游戏画质和隐藏选项。

问题在于,这份契约天然存在矛盾。

从人的角度,我们想要的是:

  • 好看、好写、层级清晰
  • 最好支持注释,方便自己和别人回来看
  • 能少写就少写,最好还能复用和模块化
  • 写错时别一碰就炸

但从机器的角度,它并不关心优不优雅,只关心两件事:

  • 解析要快
  • 规则要严,类型要清楚,最好没有歧义

这就是为什么配置文件格式总是在“人类友好”和“机器友好”之间拉扯。越适合人阅读的格式,机器往往解析更麻烦;越适合机器高效处理的格式,人写起来通常越容易崩溃。

02 INI:简单直白,但能力有限

先从 INI 说起。

它的优点非常直接:

  • 结构简单
  • 分区加键值对,几乎一眼就能看懂
  • 支持注释
  • 很适合一些轻量配置场景,比如游戏参数微调、基础环境设置

如果你改过老游戏配置,或者手动调过一些工具参数,基本都见过它。

INI 的问题也很明显。它的结构太扁平,原生不适合表达复杂嵌套和数组。再加上它通常缺少严格的类型系统,很多值本质上就是一串文本,最终怎么解释,要靠程序自己处理。

所以 INI 更像是一台老式但顺手的工具车,轻活很好用,复杂项目就容易力不从心。

例如一个很典型的 INI 配置会长这样:

1
2
3
4
5
6
[server]
host=127.0.0.1
port=8080

[feature]
enable_cache=true

03 XML:严谨、稳定,但写起来很累

第二位是 XML

如果你维护过老 Java 项目,或者见过一大堆成对闭合标签的配置文件,对它应该不陌生。

XML 的优点是:

  • 层级结构明确
  • 支持注释
  • 规则严整
  • 可以配合 schema 做强校验

这意味着机器在正式读取前,就能先知道字段类型、出现次数和结构约束,安全感很高。

但它对人的折磨也很经典:

  • 标签冗长
  • 视觉噪音很大
  • 文件容易膨胀
  • 稍微漏一个闭合标签,就可能整页报错

所以 XML 非常像一份盖章齐全的正式合同。机器喜欢,人工维护 often 很累。如今很多新项目已经不再优先选它,但在一些老系统和严规则场景里,它依然没有完全退场。

同样的配置如果写成 XML,大概会是这样:

1
2
3
4
5
6
7
8
9
<config>
  <server>
    <host>127.0.0.1</host>
    <port>8080</port>
  </server>
  <feature>
    <enable_cache>true</enable_cache>
  </feature>
</config>

04 JSON:数据交换霸主,但不适合手写复杂配置

说到现代开发,JSON 几乎绕不过去。

JSON 来说,一个很典型的判断是:作为数据交换格式,它非常强;但作为人工维护的配置文件,它有点别扭。

它的优势包括:

  • 对象和数组结构清晰
  • 网络传输友好
  • 解析器成熟
  • 对 Web API 和前后端通信非常合适

尤其和 XML 放在一起时,JSON 的轻量优势会非常明显。同样的数据结构,JSON 通常更短,也更适合在网络里传来传去。

但它有个致命缺点:标准 JSON 不支持注释。

另外,它的语法也比较严格:

  • key 必须带双引号
  • 最后一项后面不能多逗号
  • 少一个符号就会直接报错

所以 JSON 很适合 API、服务之间的数据交换,却不总是适合手动维护、需要写说明、需要频繁修改的配置文件。

比如:

1
2
3
4
5
6
7
8
9
{
  "server": {
    "host": "127.0.0.1",
    "port": 8080
  },
  "feature": {
    "enable_cache": true
  }
}

05 YAML:可读性很强,但缩进和隐式类型会坑你

如果你碰过 Docker、CI/CD、Kubernetes、自动化部署,基本一定和 YAML 打过交道。

它最吸引人的地方,就是看起来很“干净”:

  • 少了很多大括号和引号
  • 用缩进表达层级
  • 支持注释
  • 还能做锚点复用

所以从人的第一眼体验来说,YAML 通常比 JSON 友好得多。

但问题也正出在这里。它把很多复杂性藏起来了,实际使用时经常出现两类经典事故:

  • 缩进地狱
  • 隐式类型转换

缩进问题很好理解,空格多一个少一个,配置就可能直接坏掉。更麻烦的是隐式类型转换,比如某些看起来像普通字符串的值,可能会被自动解释成布尔值或别的类型。

这也是为什么很多人一边夸 YAML 好看,一边又被它折腾得很惨。它在人类阅读体验上确实很好,但机器解析它时并不轻松,而且不同解析库之间还可能有细微差异。

同样的配置写成 YAML,通常会更清爽:

1
2
3
4
5
6
server:
  host: 127.0.0.1
  port: 8080

feature:
  enable_cache: true

06 TOML:在可读性和确定性之间找平衡

TOML 经常被放在“当代均衡答案”的位置上。

TOML 的好处在于,它有点像把 INI 的直观和 JSON 的类型明确结合在一起:

  • 支持注释
  • 结构清楚
  • 强类型更明确
  • 日期时间等常见类型支持更自然
  • 不容易出现 YAML 那种隐式转换坑

尤其在现代工具链里,TOML 已经越来越常见,比如 Pythonpyproject.toml

当然它也不是没有缺点。对于很深层的嵌套结构,TOML 会显得有点啰嗦,路径式书写写多了会烦。但如果场景是中小型项目配置、工具配置、包管理配置,TOML 的整体体验往往比较稳。

如果你想找一种“注释有、语义清、机器也不难受”的格式,TOML 确实值得优先考虑。

一个常见的 TOML 写法会像这样:

1
2
3
4
5
6
[server]
host = "127.0.0.1"
port = 8080

[feature]
enable_cache = true

07 .conf 和 Apache 配置:不是通用格式,而是领域语法

有一点很值得提醒:很多人看到 .conf,会误以为它是一种统一格式,其实不是。

.conf 只是“configuration”的后缀名,里面到底怎么写,完全看具体系统自己的规则。也就是说,.conf 更像一个大类,不是一套标准语法。

Apache 配置举例,它的配置方式很有代表性:

  • 一部分像单行指令
  • 一部分又像带作用域的标签结构
  • 很适合 Web 服务器这种特定领域

优点是对运维场景很顺手,表达权限、路由、虚拟主机这类规则比较自然;问题是它几乎只服务于自己的生态,不具备很强的通用性。

所以这类配置更像“领域专用语言”,在特定系统里很好用,但不适合拿来当通用配置格式看待。

例如一个极简的 Apache 风格配置,会更像一组指令:

1
2
3
4
5
6
Listen 80

<VirtualHost *:80>
    ServerName example.com
    DocumentRoot "/var/www/html"
</VirtualHost>

08 Protocol Buffers:工业级强类型方案,但门槛高

Protocol Buffers 其实已经不是传统意义上的“随手写个配置文件”了,而更像一套正式的数据定义和序列化方案。

它的优势很强:

  • 强类型
  • schema 明确
  • 向前向后兼容性好
  • 二进制传输体积小
  • 机器处理效率很高

但代价也很明显:

  • 需要先写 .proto
  • 需要工具链和编译步骤
  • 对小项目来说门槛偏高

所以它不适合“我就配个小工具”的轻量场景,但如果你是在做大型系统、RPC、分布式服务或者长期演进的数据协议,它会比很多轻量配置格式更可靠。

它的写法更接近“先定义结构,再生成代码”:

1
2
3
4
5
6
7
syntax = "proto3";

message ServerConfig {
  string host = 1;
  int32 port = 2;
  bool enable_cache = 3;
}

09 在 AI Agent 时代,Markdown 可能重新变成“配置方式”

最有意思的部分,是把 Markdown 也算进了“配置文件”的讨论里。

这在传统程序视角里听起来有点奇怪,因为 Markdown 本来更像文档格式。但如果把对象换成大语言模型和 AI Agent,这个判断其实是成立的。

为什么?

因为传统程序依赖的是严格语法和固定字段,而大模型更擅长理解语义、结构和上下文。对于它们来说:

  • 标题就是层级
  • 列表就是步骤
  • 加粗就是强调
  • 自然语言本身就能承载规则

也就是说,当配置对象从“死板的解析器”变成“能读懂语义的 Agent”,Markdown 这类人类友好的结构化文本,反而可能成为一种更自然的配置形式。

这也是一个很关键的判断:在传统软件时代,很多配置格式是为了让人去适应机器;而在 AI 时代,机器开始反过来适应人的表达。

比如给 Agent 写任务配置,完全可能直接写成这样:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 任务目标

为新用户写一封欢迎邮件。

## 要求

- 语气友好
- 不超过 150 字
- 提到产品的 3 个核心功能

## 禁止事项

- 不要承诺不存在的功能
- 不要使用夸张营销语气

10 到底该怎么选

如果把这些观点压缩一下,我觉得可以简单分成这样几类:

  • 想要极简、轻量、扁平配置:INI
  • 想要强结构、强校验、老系统兼容:XML
  • 想要网络传输和接口交换:JSON
  • 想要高可读性、云原生和部署配置:YAML
  • 想要更稳的现代通用配置体验:TOML
  • 想要特定系统内部规则:.conf / Apache 一类 DSL
  • 想要工业级协议和长期演进能力:Protocol Buffers
  • 面向 AI Agent 的自然表达和任务编排:Markdown

所以“最好的配置文件格式”其实并不存在。它取决于你是在为谁写:

  • 为人维护
  • 为机器高速解析
  • 为服务之间通信
  • 还是为 AI Agent 理解和执行

简单总结

配置文件的发展史,本质上就是人和机器不断重新分配理解成本的过程。

过去是人迁就机器,所以我们要记各种括号、缩进、引号和严格规则。现在随着大语言模型和 Agent 系统越来越成熟,机器开始更能理解自然表达,于是“配置”这件事本身也在变化。

也许未来很多场景里,配置文件不再是某种固定格式,而更像一段结构化意图说明。而在那之前,JSONYAMLTOMLINIXML 这些格式依然会长期共存,各自占据最适合自己的位置。

记录并分享
使用 Hugo 构建
主题 StackJimmy 设计