是时候使用 YAML 来做配置或数据文件了
概述
我们做程序,经常需要用到配置信息,回顾一下这么多年的搬砖生涯,我记得用过多种格式的文件来定义配置信息,例如 ini文件
,xml文件
,或者现在比较流行的 json
文件。
这些年随着云计算和云原生应用的流行,我发现一种新的做配置(甚至作为数据源格式)的文件格式,叫做 YAML
(发音 /ˈjæməl/ )。看这个名字,好像它又是一种新的 ML(Markup Language)
,出人意外的是据说它的这个名字的本意是指 YAML Ain't Markup Language
,当然也有人调侃地说,其实是指 Yet Another Markup Language
。 我们不管这么多,今天主要来看看具体怎么使用它,以及它跟之前的格式(尤其是 json
)有什么关系和区别?
一个简单的例子
YAML文件一般以 .yml
作为扩展名,例如下面这个例子是介绍了我的博客基本信息。我们可以看到非常简洁的语法,例如
- 在冒号(
:
) 的两边定义了属性名和属性值。 - 不同属性,换行即可。
- 如果表示一个数组,则用
-
定义条目。 - 多行文本属性值,用
|
定义。 - 不同的层级用缩进即可。
title: 陈希章@中国
author: 陈希章
link: https://chenxizhang.cnblogs.com
description: |
这是陈希章在博客园的主页,
这个博客是从2005年开始撰写的,目前有随笔约1400篇
tags:
- 科技
- 人文
languages:
- en-us
- zh-cn
articles:
- title: 使用本地自签名证书为 React 项目启用 https 支持
href: https://www.cnblogs.com/chenxizhang/p/16244358.html
- title: 在博客文章中使用mermaid 定义流程图,序列图,甘特图
href: https://www.cnblogs.com/chenxizhang/p/16253501.html
与其他格式的比较
我们来看一下,如果这个文件用 json
来定义应该怎么样呢?
{
"title": "我的博客",
"author": "陈希章",
"link": "https://chenxizhang.cnblogs.com",
"description": "这是陈希章在博客园的主页,\n这个博客是从2005年开始撰写的,目前有随笔约1400篇\n",
"tags": [
"科技",
"人文"
],
"languages": [
"en-us",
"zh-cn"
],
"articles": [
{
"href": "https://www.cnblogs.com/chenxizhang/p/16244358.html",
"title": "使用本地自签名证书为 React 项目启用 https 支持"
},
{
"href": "https://www.cnblogs.com/chenxizhang/p/16253501.html",
"title": "在博客文章中使用mermaid 定义流程图,序列图,甘特图"
}
]
}
简单比较一下,同样的数据,用 json
需要 612 个字符,而用 YAML
则需要 410个字符,节约大约200个字符呢,也就是相当于省了1/3的体积。
如果是XML
会更加繁琐,这里就不比较了。
就算是一直来说已经算比较简洁的 json
,为了表示一个数据结构,不得不引入很多跟内容无关的字符,包括 {
和 }
表示一个对象的开始和结束,[
和 ]
表示一个数字的开始和结束,另外不同的属性之间还要用 ,
分开,如果有多行文本,需要用 \n
来分割。
定义schema来辅助输入和验证
在使用 XML
或 json
文件格式时,我们都可以通过架构文件(schema)来让编辑器提供智能提示,并且也可以在程序中对内容进行校验。例如如果我们要验证上面这个json
文件,可以定义如下的schema
文件
{
"$schema": "http://json-schema.org/draft-07/schema",
"$id": "https://www.xizhang.com/schemas/blog",
"title": "博客数据",
"type": "object",
"properties": {
"title": {
"type": "string",
"description": "博客标题"
},
"author": {
"type": "string",
"description": "作者信息"
},
"link": {
"type": "string",
"description": "博客链接地址"
},
"description": {
"type": "string",
"description": "博客描述信息,可以多行"
},
"tags": {
"type": "array",
"description": "标签信息,可以有多个",
"items": {
"type": "string"
}
},
"languages": {
"type": "array",
"description": "支持的语言列表",
"items": {
"type": "string"
}
},
"articles": {
"type": "array",
"description": "文章列表",
"items": {
"type": "object",
"title": "文章",
"description": "文章信息",
"properties": {
"title": {
"type": "string",
"description": "文章标题"
},
"href": {
"type": "string",
"description": "文章链接"
}
},
"required": [
"title"
]
}
}
},
"required": [
"title",
"author",
"link",
"articles"
]
}
注意,编写这个文档本身不难,你输入第一行 $schema
并且选择其中一个标准版本,例如 http://json-schema.org/draft-07/schema
之后,下面就都有智能提示,所以不要过分依赖所谓网上很多的生成器。
如果在json
文件中使用这个schema,语法如下
{
"$schema": "./blogschema.json",
"title": "我的博客",
"author": "陈希章",
"link": "https://chenxizhang.cnblogs.com",
"description": "这是陈希章在博客园的主页,\n这个博客是从2005年开始撰写的,目前有随笔约1400篇\n",
"tags": [
"科技",
"人文"
],
"languages": [
"en-us",
"zh-cn"
],
"articles": [
{
"href": "https://www.cnblogs.com/chenxizhang/p/16244358.html",
"title": "使用本地自签名证书为 React 项目启用 https 支持"
},
{
"href": "https://www.cnblogs.com/chenxizhang/p/16253501.html",
"title": "在博客文章中使用mermaid 定义流程图,序列图,甘特图"
}
]
}
除了用相对路径指定schema文件外,还可以用网络地址,例如 "$schema": "https://files.cnblogs.com/files/chenxizhang/blogschema.json"
有意思的是,YAML
也是使用json
schema来做架构验证和智能提示,如果你用vscode
作为编辑器,你可以安装一个插件如下
接下来在你的 yml
文件的顶部插入这样一句 # yaml-language-server:$schema=https://files.cnblogs.com/files/chenxizhang/blogschema.json
然后再进行输入时,就会有智能提示,包括了描述信息等
如果你的数据信息不完整,vscode
会有明确的提示
我们还可以让 vscode
自动给相关文件套用对应的schema,例如我们想让当前目录中所有带有 blog
的 .yml
文件,都自动地套用 https://files.cnblogs.com/files/chenxizhang/blogschema.json
这个schema,可以这么做
- 在当前项目根目录下面创建
.vscode
目录 - 在
.vscode
目录中创建settings.json
文件
输入如下的内容
{
"yaml.schemas": {
"https://files.cnblogs.com/files/chenxizhang/blogschema.json": "*blog.yml"
}
}
在不同的开发语言中使用 YAML
下面演示一些代码的例子,展示如何在不同的语言中读写 YAML 文件
PowerShell
首先需要安装一个模块,Install-Module -Name powershell-yaml
通过 Get-Content .\blog.yml -Encoding utf8 | ConvertFrom-Yaml
可以读取一个.yml
文件并且显示其结果
通过 ConvertTo-Yaml
可以把一个对象转换为 yaml
文本,例如 $PSVersionTable | ConvertTo-Yaml
得到的结果如下
.NET Core (c#) 控制台程序
首先需要安装一个组件,dotnet add package YamlDotNet --version 11.2.1
通过下面的代码可以解析某个文件内容
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;
// 读取yaml文件
using (TextReader reader = File.OpenText("test.yml"))
{
var deserializer = new DeserializerBuilder().WithNamingConvention(UnderscoredNamingConvention.Instance).Build();
dynamic output = deserializer.Deserialize(reader);
Console.WriteLine(output["title"]);
}
通过下面的代码可以将对象写入到 yaml文件中去
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;
// 写入yaml文件
var person = new
{
Name = "张三丰",
Age = 25,
Addresses = new Dictionary<string, object>{
{ "home", new {
Street = "东直门",
City = "北京",
State = "北京",
Zip = "111111",
}},
{ "work", new {
Street = "王府井",
City = "北京",
State = "北京",
Zip = "222222",
}},
}
};
var serializer = new SerializerBuilder()
.WithNamingConvention(CamelCaseNamingConvention.Instance)
.Build();
var yaml = serializer.Serialize(person);
System.Console.WriteLine(yaml);