配置文件格式详解
做开发和运维,配置文件是绕不开的东西。选对格式能省很多事,选错了后期维护就是噩梦。这里把主流的配置文件格式都过一遍,说清楚各自的特点和适用场景。
JSON
JSON 是最通用的配置格式,几乎所有编程语言都能解析。语法简单,就是键值对和嵌套对象。
优点:
- 语法简单,学习成本低
- 所有语言都有原生支持
- 数据类型明确(字符串、数字、布尔、数组、对象、null)
- Schema 验证工具成熟(JSON Schema)
缺点:
- 不支持注释,这是最大的痛点
- 尾逗号会报错,复制粘贴时容易出错
- 字符串必须用双引号,配置文件里写起来不够简洁
- 多行字符串需要转义,写 SQL 或证书内容很痛苦
适用场景: API 响应、package.json、tsconfig.json 这类程序生成或消费的配置。
{
"name": "my-app",
"version": "1.0.0",
"dependencies": {
"express": "^4.18.0"
},
"scripts": {
"start": "node index.js"
}
}YAML
YAML 专门为人写配置设计的,缩进表示层级关系,可读性很好。Docker Compose、Kubernetes、GitHub Actions 都用它。
优点:
- 支持注释,用
#开头 - 语法简洁,没有多余符号
- 支持多行字符串(
|保留换行,>折叠换行) - 支持锚点和引用,可以复用配置片段
缺点:
- 缩进敏感,Tab 和空格混用会出问题
- 隐式类型转换坑多(
yes会被解析成true,1.0变成浮点数) - 解析比 JSON 慢
- 错误提示不够友好,缩进错了很难定位
适用场景: Docker Compose、Kubernetes 清单、CI/CD 配置、Ansible Playbook。
# Docker Compose 示例
version: '3.8'
services:
web:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
depends_on:
- api
api:
build: .
environment:
NODE_ENV: production
DATABASE_URL: postgres://db:5432/myapp
restart: unless-stoppedTOML
TOML 设计目标就是做配置文件,语义清晰,类型明确。Rust 的 Cargo、Python 的 pyproject.toml 都用它。
优点:
- 支持注释
- 类型系统严格,不会出现 YAML 那种隐式转换
- 表格结构清晰,用
[section]表示层级 - 日期时间有原生支持
- 尾逗号合法
缺点:
- 嵌套太深时可读性下降
- 数组里放表格的语法有点奇怪(
[[array]]) - 比 JSON 和 YAML 小众,部分工具支持不完善
适用场景: Rust/Cargo、Python/pyproject.toml、Hugo 配置、系统工具配置。
# Cargo.toml 示例
[package]
name = "my-project"
version = "0.1.0"
edition = "2021"
[dependencies]
serde = { version = "1.0", features = ["derive"] }
tokio = { version = "1", features = ["full"] }
[dev-dependencies]
criterion = "0.5"
[[bench]]
name = "my_benchmark"
harness = falseINI
INI 是最古老的配置格式之一,Windows 系统大量使用。结构简单,适合扁平配置。
优点:
- 语法极其简单,人人都能看懂
- 支持注释(
;或#) - 解析速度快
缺点:
- 没有官方标准,不同解析器行为不一致
- 不支持嵌套结构
- 数据类型只有字符串
- 数组支持靠约定(重复键或逗号分隔)
适用场景: 简单的键值配置、.gitignore、Python 的 setup.cfg。
[database]
host = localhost
port = 5432
user = admin
password = secret123
dbname = myapp
[logging]
level = INFO
file = /var/log/app.logXML
XML 曾经是配置文件的主流选择,现在主要用于 Java 生态和需要 Schema 验证的场景。
优点:
- Schema 验证完善(XSD、DTD)
- 支持命名空间
- 属性和元素两种表达方式
- 注释支持良好
缺点:
- 冗余标签太多,文件体积大
- 可读性比 JSON 和 YAML 差
- 解析开销大
适用场景: Maven/pom.xml、Spring 配置、SOAP API、Android 布局。
<!-- Maven pom.xml 片段 -->
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>my-app</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>3.1.0</version>
</dependency>
</dependencies>
</project>ENV
.env 文件用于管理环境变量,Docker 和各种框架都支持。格式就是 KEY=VALUE。
优点:
- 格式最简单,没有任何学习成本
- 和操作系统环境变量无缝对接
- .gitignore 容易管理,敏感信息不会提交
缺点:
- 只有扁平的键值对
- 没有数据类型,全是字符串
- 不支持注释内联(注释必须独占一行)
- 不同工具解析行为不一致
适用场景: Docker 环境变量、应用密钥配置、本地开发配置。
# .env 示例
NODE_ENV=production
PORT=3000
DATABASE_URL=postgres://user:pass@localhost:5432/db
REDIS_URL=redis://localhost:6379
SECRET_KEY=your-secret-key-hereHCL
HCL(HashiCorp Configuration Language)是 Terraform 和 Vault 专用的配置语言,兼顾人可读性和机器解析。
优点:
- 语法接近自然语言
- 支持表达式和函数
- 块结构清晰
- 注释支持
缺点:
- 主要限于 HashiCorp 生态
- 学习曲线比 JSON 陡
- 第三方工具支持少
适用场景: Terraform 基础设施即代码、Vault 配置、Consul 配置。
# Terraform 配置示例
provider "aws" {
region = "us-east-1"
}
resource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
tags = {
Name = "HelloWorld"
}
}Properties
Java 的 .properties 文件,格式和 .env 类似,但在 Java 生态里根深蒂固。
优点:
- Java 原生支持
- 格式简单
- 支持 Unicode 转义
缺点:
- 只支持扁平键值对
- 没有数据类型
- 编码问题(默认 ISO-8859-1)
适用场景: Spring Boot 配置、Java 应用国际化、Maven settings。
# application.properties
server.port=8080
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=root
spring.datasource.password=secret格式选择建议
选配置文件格式没有银弹,看你的具体需求:
| 场景 | 推荐格式 | 理由 |
|---|---|---|
| API 数据交换 | JSON | 通用性最好 |
| Docker/K8s | YAML | 生态约定 |
| Rust/Go 项目 | TOML | 类型安全 |
| 基础设施即代码 | HCL | 专为此设计 |
| 环境变量 | .env | 简单直接 |
| Java 项目 | Properties/YAML | 框架支持 |
| 简单键值 | INI | 最易上手 |
几个实用建议:
- 能用注释就别用 JSON —— 配置文件需要注释说明意图,JSON 这点太反人类
- 人写的配置优先 YAML/TOML —— 可读性好,写起来舒服
- 机器生成的配置用 JSON —— 程序解析和生成都方便
- 敏感信息用 .env —— 容易和 .gitignore 配合
- 团队统一最重要 —— 选团队最熟悉的格式,别折腾
配置文件最佳实践
不管用哪种格式,这些原则都适用:
分离环境配置
别把所有环境的配置混在一起:
config/
├── default.yml # 默认配置
├── development.yml # 开发环境
├── staging.yml # 预发布环境
└── production.yml # 生产环境敏感信息不要提交
密钥、密码、Token 这类东西绝对不能进 Git:
# .gitignore
.env
.env.local
*.pem
secrets.yml使用 Schema 验证
JSON 和 YAML 都支持 Schema,能在启动前发现配置错误:
// JSON Schema 示例
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": ["port", "database"],
"properties": {
"port": {
"type": "integer",
"minimum": 1024,
"maximum": 65535
},
"database": {
"type": "object",
"required": ["host", "port"],
"properties": {
"host": { "type": "string" },
"port": { "type": "integer" }
}
}
}
}配置即文档
好的配置文件应该自解释:
# 差的写法
timeout: 30
# 好的写法
# API 请求超时时间,单位秒。网络不好的环境可以适当调大。
api:
request_timeout: 30版本化配置
配置文件也要版本管理,但敏感信息除外:
# 配置模板提交到 Git
config.yml.example
# 实际配置不提交
config.yml