目录
- 1. YAML语法
- 1.1 Scalars
- 1.2 Array
- 1.3 Object
- 1.4 复杂结构
- 1.5 高级用法
- 1.5.1 浮点数特殊值
- 1.5.2 锚点与别名
- 1.5.3 合并键
- 2. PyYAML的使用
- 2.1 解析YAML
- 2.2 生成YAML
- 3. YAML和JSON的区别
- Ref
1. YAML语法
YAML(YAML Ain’t Markup Language)是一种用于数据序列化的格式,广泛用于配置文件、数据交换等场景。它以其易于阅读和书写的特性而受到欢迎。YAML的设计目标是易于人类阅读和编写,同时也易于计算机解析和生成。
YAML配置文件的后缀名通常为 .yml
或 .yaml
(前者用的较多)。
一些注意事项:
- YAML对大小写敏感。
- YAML不允许使用Tab,只允许使用空格。
- YAML用缩进表示层级关系。缩进的空格数目不重要,只要相同层级的元素左侧对齐即可。
- YAML支持注释,使用
#
代表注释行。
🧑💻 如果说JSON像C++,那么YAML就像Python,语法简洁而优雅,没有那么多冗余的大括号,方括号以及引号。
回顾JSON,它支持以下数据类型:
Object
:由{}
括起来的一组无序键值对。其中键必须是字符串,值可以是JSON支持的任意数据类型,包括Number、String、Boolean、Null、Array和Object本身。Array
:可以存放JSON支持的任意数据类型。Scalars
:包括Number、String、Boolean、Null。
YAML和其类似,只不过在 Scalars
中还支持日期和日期时间,以ISO 8601的格式进行表示。
📝 在ISO 8601标准下,日期格式为
YYYY-MM-DD
,日期时间格式为YYYY-MM-DDTHH:MM:SS[+/-]HH:MM
。其中T
用来分隔日期和时间,+
或-
表示相对于UTC时间的偏移。如果时间本身就是UTC时间,那么日期时间格式为YYYY-MM-DDTHH:MM:SSZ
,其中Z
代表"Zulu time",也就是协调世界时(UTC)。
1.1 Scalars
先来看Scalars是什么样的:
string: "Hello, YAML"
boolean: true
integer: 123
float: 3.14
null: null
null2: ~
null3:
date: 2018-02-17
datetime: 2018-02-17T15:02:31+08:00
utctime: 2018-02-17T15:02:31Z
其对应的JSON为:
{"string": "Hello, YAML","boolean": true,"integer": 123,"float": 3.14,"null": null,"null2": null,"null3": null,"date": "2018-02-17T00:00:00.000Z","datetime": "2018-02-17T07:02:31.000Z","utctime": "2018-02-17T15:02:31.000Z"
}
可以看出YAML中的 null
有三种表示方式,而JSON只有一种。此外,JSON中的日期和时间全为字符串格式。
1.2 Array
再来看Array是什么样的:
items:- Apple- Banana- Cherry
其对应的JSON为:
{"items": ["Apple","Banana","Cherry"]
}
1.3 Object
最后看Object是什么样的:
person:name: John Doeage: 30
其对应的JSON为:
{"person": {"name": "John Doe","age": 30}
}
1.4 复杂结构
YAML支持数据的嵌套,允许创建复杂的数据结构。
family:parent: name: John Doeage: 40employed: trueaddress:street: 1234 Maple Streetcity: Anytownstate: Anystatezip: 12345coordinates:latitude: 40.7128longitude: -74.0060children:- name: Jane Doeage: 12hobbies:- Reading- Swimminggrade: 7favorite_color: "blue"- name: Doe Juniorage: 8hobbies:- Biking- Gaminggrade: 3favorite_color: "green"pets:- type: Dogname: Roverage: 5- type: Catname: Whiskersage: 3likes_water: falsevacation_spots:- location: "Paris, France"visited: true- location: "Tokyo, Japan"visited: falsehome_utilities:electricity: truegas: truewater: trueinternet_service_provider: null
其对应的JSON为:
{"family": {"parent": {"name": "John Doe","age": 40,"employed": true},"address": {"street": "1234 Maple Street","city": "Anytown","state": "Anystate","zip": 12345,"coordinates": {"latitude": 40.7128,"longitude": -74.006}},"children": [{"name": "Jane Doe","age": 12,"hobbies": ["Reading","Swimming"],"grade": 7,"favorite_color": "blue"},{"name": "Doe Junior","age": 8,"hobbies": ["Biking","Gaming"],"grade": 3,"favorite_color": "green"}],"pets": [{"type": "Dog","name": "Rover","age": 5},{"type": "Cat","name": "Whiskers","age": 3,"likes_water": false}],"vacation_spots": [{"location": "Paris, France","visited": true},{"location": "Tokyo, Japan","visited": false}],"home_utilities": {"electricity": true,"gas": true,"water": true,"internet_service_provider": null}}
}
1.5 高级用法
1.5.1 浮点数特殊值
YAML支持浮点数特殊值,而JSON不支持(会以 null
显示),所以我们要将其转化成Python对象然后打印出来。
+inf: .inf
-inf: -.inf
nan: .nan
转化成Python对象后:
{'+inf': inf, '-inf': -inf, 'nan': nan}
1.5.2 锚点与别名
YAML中的锚点(Anchors)和别名(Aliases)提供了一种强大的机制,允许你在YAML文档中定义一个值或对象,并在文档的其他地方通过引用来重用这个值或对象。这种机制既可以提高配置文件的可维护性,也可以减少重复内容,使得YAML文件更加简洁和易于管理。
锚点允许你标记一个特定的位置,你可以在YAML文件的任何地方定义一个锚点。创建锚点时,你需要使用 &
符号,后面跟上锚点的名称。这个名称是你自定义的,可以是任何有效的字符串,用来在稍后引用这个锚点。
一旦定义了锚点,就可以通过别名在文档的其他地方引用它。创建别名时,使用 *
符号,后面跟上之前定义的锚点名称。通过这种方式,你可以多次引用同一个锚点,无论是值、数组还是对象。
例1(对Scalars创建锚点):
default_path: &defaultPath /usr/local/binpathA: *defaultPath
pathB: *defaultPath
对应的JSON为
{"default_path": "/usr/local/bin","pathA": "/usr/local/bin","pathB": "/usr/local/bin"
}
例2(对Array创建锚点):
default_ports: &ports- 80- 443serviceA:ports: *portsserviceB:ports: *ports
对应的JSON为
{"default_ports": [80,443],"serviceA": {"ports": [80,443]},"serviceB": {"ports": [80,443]}
}
例3(对Object创建锚点):
default_server: &serverConfighost: localhostport: 8080development:server: *serverConfigproduction:server: *serverConfig
对应的JSON为
{"default_server": {"host": "localhost","port": 8080},"development": {"server": {"host": "localhost","port": 8080}},"production": {"server": {"host": "localhost","port": 8080}}
}
1.5.3 合并键
<<
可以将一个Object的所有键值对合并到另一个Object中,方便重用。
base: &basea: 1b: 2other:<<: *basec: 3d: 4
对应的JSON格式为
{"base": {"a": 1,"b": 2},"other": {"a": 1,"b": 2,"c": 3,"d": 4}
}
我们还可以基于此进行键值对的更新:
default_server: &serverConfighost: localhostport: 8080development:<<: *serverConfigport: 8081production:<<: *serverConfighost: example.com
对应的JSON为
{"default_server": {"host": "localhost","port": 8080},"development": {"host": "localhost","port": 8081},"production": {"host": "example.com","port": 8080}
}
2. PyYAML的使用
安装:
pip install pyyaml
导入:
import yaml
2.1 解析YAML
从YAML字符串或文件中加载数据时,yaml.load()
函数可以将YAML文档转换为Python字典对象。出于安全考虑,推荐使用 yaml.safe_load()
,它只加载安全的 YAML 子集。
# 从字符串解析
yaml_str = """
a: 1
b:- 2- 3
"""
data = yaml.safe_load(yaml_str)
print(data)# 从文件解析
with open('example.yml', 'r') as f:data = yaml.safe_load(f)print(data)
2.2 生成YAML
yaml.dump()
函数可以将Python字典对象转换为YAML格式的字符串。你还可以将输出直接写入文件。
data = {'a': 1,'b': [2, 3]
}# 生成 YAML 字符串
yaml_str = yaml.dump(data)
print(yaml_str)# 写入文件
with open('output.yml', 'w') as f:yaml.dump(data, f)
通常 dump()
方法会对所有 key
按字典序进行排序,为避免排序,可以这样设置:
yaml.dump(data, f, sort_keys=False)
3. YAML和JSON的区别
YAML和JSON都是用于数据交换和存储的文本格式,它们在某些方面具有相似性,但也有几个关键的区别:
可读性:
- YAML:设计时就考虑到了可读性,它使用了缩进式的结构来表示数据层次,不使用大括号和方括号来表示对象和数组,这使得它在人类读写方面更加友好。
- JSON:虽然也是文本格式,但使用大括号表示对象,方括号表示数组,逗号分隔键值对或数组元素,这使得它在机器解析方面更高效,但在人类阅读和编写时可能不如YAML直观。
数据类型支持:
- YAML:支持字符串、数字、日期、null、布尔值、数组、映射等类型,还支持更复杂的类型,如二进制数据和可以自定义类型的能力。
- JSON:支持的基本数据类型有字符串、数字、对象(映射)、数组、布尔值和null。
注释:
- YAML:支持使用井号(
#
)添加注释,这对于解释或说明配置文件中的特定部分非常有用。 - JSON:标准的JSON格式不支持注释,尽管一些JSON处理器可能会提供对注释的支持,但这并非广泛接受的标准。
冗余度:
- YAML:由于其设计注重人类的可读性和书写简便,它可能在表示相同的数据结构时比JSON更加简洁。
- JSON:因为需要使用额外的符号(如大括号和方括号),在表示复杂的数据结构时可能比YAML更加冗长。
解析复杂性:
- YAML:其灵活性和对复杂数据类型的支持使得解析器相对更复杂,解析过程可能比JSON慢。
- JSON:由于其结构简单,解析器通常更快,更少的内存占用,这在处理大量数据时尤其重要。
用途:
- YAML:常用于配置文件、数据交换等场景,特别是在需要高度可读性和人类编辑的环境中。
- JSON:由于其简洁性和快速解析的特性,广泛用于网络传输、API交互等需要高效数据交换的场景。
Ref
[1] https://www.ruanyifeng.com/blog/2016/07/yaml.html
[2] https://www.runoob.com/w3cnote/yaml-intro.html
[3] https://codebeautify.org/yaml-to-json-xml-csv