常见配置文件格式基础认知(YAML / JSON / XML / INI)
JSON 格式
JSON 全称 JavaScript Object Notation(JavaScript 对象表示法),最开始只是 JS 中用来表示对象的一种文本格式,后来因为它非常适合做数据交换,就独立成了一种通用数据格式。
JSON 通过 对象和 数组 两种方式来组织结构:
- 对象:使用大括号
{ }包括的若干个键值对。 - 数组:使用 中括号
[ ]包裹的一组值。
# 对象结构
{ "name": "Tom","age": 18 }
# 数组结构
[ "Tom", 18, true, null, {"city": "Beijing"} ]
JSON 的基本结构由对象(键值对集合)和数组(值列表)组成,所以键值对需要遵循以下规则才能正确被解析:
- 键(Key)必须且只能使用双引号包裹。因为 JSON 规定 Key 只能是字符串类型,JSON 中的字符串只能使用双引号包裹。
- 键(Key)和 Value(值)之间使用冒号
:分隔,冒号两侧是否有空格无强制要求,不影响解析。 - 多个键值对使用逗号
,分隔,最后一个元素后不能有多余的逗号; - Value 支持多种数据类型,包括:字符串、数字、布尔值、对象、数组、null,需注意 JSON 中字符串只能用双引号包裹,用单引号不行,而且 布尔值 只能是 小写的
true或false
XML 格式
早期数据交换没有统一的格式,互联网又在此时爆发增长,所以就急需一种能让机器容易解析,让人也能读懂的数据格式,W3C 就推出了简化版的 SGML,也就是现在的 XML
XML 全称是 eXtensible Markup Language(可扩展标记语言),通过 标签 来组织结构,而且标签不是预定义好的,可以根据实际需求来自定义,用以表达语义。如:MySQL的配置文件就是使用 INI 这种格式组织的。
XML 中的标签就是 通过尖括号 <> 来定义,尖括号里面写标签名。例如:<tag_name>
XML 由 元素(Element)、属性(Attribute)和文本内容(Text)三部分组成:
- 元素:由一对开始标签和结束标签 组成,开始标签:
<tag_name>,结束标签:</tag_name> - 内容:在元素(也就是开始标签和结束标签)之间的文本内容(若标签没有具体内容,可以使用自闭合标签
<tag_name />) - 属性:在开始标签中定义,格式为:key="value",属性值必须使用引号包裹(单引号或双引号均可),多个属性使用空格分隔。
XML 需要遵循以下规则才能被正确解析:
- 定义标签名时,标签名不能以 数字或 “xml” 开头,且标签要有始有终,也就是每个标签都必须闭合
- 整个 XML 文档最外层只能有一个元素包住所有内容,其他元素要作为它的子元素,而且标签必须正确嵌套,不能交叉。可以把开始标签理解为:
(,结束标签理解为),交叉了肯定不行。 - XML 大小写敏感,意思就是开始标签和结束标签的大小写必须完全一致。如:开始标签是
<Name>,结束标签就必须是:</Name> - XML支持注释,注释格式为:
<!-- 注释 -->
INI 格式
INI 的起源早于 XML 和 JSON,早期 DOS 系统中的程序没有统一的配置格式标准,直接将配置写死在代码里,改配置就要重新编译,所以随着 Windows 系统流行起来,INI 也就流行起来了。
INI 全称 Initialization File ,通过 节(Section)来组织结构,通过 节(Section)来给配置分类,避免所有配置混在一起。
INI 的配置由 节(Section)、键值对 和 注释三部分组成:
- 节(Section):一对中括号,然后里面写名称。如:[database],节 就是一个分组,从该节 开始到下一节 之间的键值对 都属于这个 节。
- 键值对:一般是采用 key = value 这种格式,并且
=两边是否存在空格无影响 ,还有就是 INI 中没有数据类型概念,本质都是字符串,所以要不要加引号无所谓,具体如何解析由程序决定。 - 注释:
#或;开头的内容都属于注释,且支持行内注释,例如:PHP 的配置文件 php.ini 就是采用 INI 这种格式。
注:Section 名可以忽略,因为 Section 的作用就是给 键值对(key = value)分组用的,如果全都在一组,就可以省略 Section 名,这样所有的 键值对 属于“默认 section”
YAML 格式
YAML 的出现是为了解决 XML、JSON 这些格式在配置文件场景不好写,也不好读的问题。所以 YAML 的出现就是想解决方便人类能轻易看懂和编写配置文件,不是为了机器交换数据而生。
XML 标签太多,太啰嗦了,看起来很累,而且文件还很长;JSON 的话不支持注释,而且多一个逗号就报错,键还必须用双引号,简直就是地狱;INI 的话,复杂的嵌套结构又不支持,只能平铺 key=value。
YAML 是通过缩进来组织结构,层级一眼就懂。不像 JSON 一样还得用 对象/数组,或 XML 的元素符号。
# json
{
"server": { "port": 8080 }
}
# xml
<server>
<port>8080</port>
</server>
# ini
[server]
port=8080
# yaml
server:
port: 8080
YAML 专为配置文件而生,做了如下的优化:
- 支持注释,使用 # 开头的行表示注释,并且也支持行内注释,这是JSON做不到的
- 不需要大量引号,Key 默认不需要加引号,Value 即使是字符串,也可以不加引号,若 key 和 value 包含特殊字符要加上。
YAML 简化了结构,也付出了对应的代价:
- 对 空格 非常敏感,缩进表示结构的时候,只能用空格,不能用tab,而且同一层级必须要使用相同的空格来对齐。
key和value用冒号:分隔时,冒号后面至少有一个空格,否则 解析器会将 key:value 当成一个字符串,从而解析失败
YAML 采用缩进来表示层级关系,最基本的结构单元是键值对(key: value),一个键值对由 key 和 value 两部分组成。
我们讨论的对象、列表这些是针对 value 这部分来说的。key 永远是一个名字,真正决定结构的是 value ,value 可以写类型的数据:
- 标量:就是一个具体的值,可以是一个字符串、数值、或布尔值。
- 列表:可以理解为数组,每个元素使用 - 开头
- 对象:就是一个或多个键值对组成
注意:YAML 中还存在一种情况,就是使用纯列表作为根节点,这个也是合法的 YAML 语法
# services 这个key 对应的 value 是一个列表,有两个元素(有几个 - 就有几个元素)
# 每个元素 又是由一个对象组成(一个对象就是一个或多个键值对)
# 对象中第一个键 对应的 value 是标量,是一个字符串,因 yaml 中无特殊字符,字符串可省略引号
# 对象中第二个键 对应的 value 是一个列表,有两个元素,每个元素都是一个标量(数值)
services:
- name: web
ports:
- 80
- 443
- name: db
ports:
- 3306
# 省略了 key,纯列表的场景
- name: node1
ip: 10.0.0.1
- name: node2
ip: 10.0.0.0.2
注意:当 某个键值对 中的 Value 是一个列表时:
- 若需要在一行表示列表的所有元素,则必须使用中括号 [],元素用逗号分隔。
- 若需要每个元素要单行表示, YAML 允许在下一行用
-直接开始这个列表,因此-可以与 key 对齐书写(必须是 key: 后已经换行的情况下,也就是 key: 后面啥都没有)
# key 换行的情况(YAML 允许用 - 直接开始这个列表,所以 - 和上层key对齐是对的)
a:
- 1
- 2
# 和上面等价(也可以缩进两个空格)
a:
- 1
- 2
# key: 不换行场景,必须 中括号 [] 一行写完
a: [1, 2]
浙公网安备 33010602011771号