C# yaml 配置文件的用法

目录

一、简介

二、yaml 的符号

1.冒号

2.短横杆

3.文档分隔符

4.保留换行符

5.注释

三、yaml 语法

1.对象

2.数组

3.字符串

4.布尔

5.数值

6.时间

结束


一、简介

YAML(YAML Ain't Markup Language)是一种数据序列化标准,广泛用于配置文件、数据交换和存储。YAML的设计目标是易于阅读和编写,同时也易于机器解析和生成。以下是YAML的一些关键特点和用途的介绍:

  1. 简洁性:yaml 使用缩进和简洁的语法来表示数据结构,这使得它比 XML 或 Json 等格式更易于阅读和编写。

  2. 数据类型支持:yaml 支持多种数据类型,包括标量(如字符串、整数、浮点数)、序列(列表)、映射(字典)以及复杂的数据结构。

  3. 跨语言支持:yaml 可以被多种编程语言解析和生成,包括 Python、Ruby、Java、JavaScript 等,这使得它在不同系统间的数据交换中非常有用。

  4. 配置文件:yaml 常用于编写配置文件,因为它的人类可读性和灵活性使得配置管理变得简单。例如,Docker 和Kubernetes 都使用 yaml 来定义容器和集群的配置。

  5. 文档分离:yaml 支持文档分离,即一个文件中可以包含多个独立的 yaml 文档,每个文档由三个破折号(---)分隔。

  6. 引用和锚点:YAML允许使用引用和锚点来避免数据重复,这可以提高数据的可维护性和减少错误。

  7. 兼容性:YAML可以与JSON相互转换,这意味着YAML文件可以很容易地转换为JSON格式,反之亦然。

yaml 有以下基本规则:

1. 大小写敏感。

2. 使用缩进表示层级关系,缩进时不允许使用Tab键,只允许使用空格键,缩进的空格数不重要,只要元素左侧能对齐就可。

3.空格,在 value 的值前边必须有空格,否则读取时会报错,比如:name:  jack,而不是 name:jack,键值对的冒号后面至少有一个空格。

4.引号,value 的值如果是字符串,可以用引号也可以不用,单引号和双引号都可以。

5. yaml 兼容 Json 的语法,插件 YamlDotNet 同样也可以读写 Json。

yaml 在读取性能上不如 Json,但在需要手写配置文件的时候,yaml 要比 Json 方便不少,不用添加那么多对称的大括号(花括号)和中括号(方括号),读起来也更简单易懂,并且在多个编程语言中都是通用的。

二、yaml 的符号

这里只介绍几个常用的符号,这不是 yaml 所有运算符,比如:使用 & 定义一个锚点,使用 * 引用已定义的锚点,使用 << 来继承锚点数据,这些符号一般用于复杂的文档,我就不写那么详细了,有需要的可以参考官方文档 The Official YAML Web Site

在使用 C# 进行读写时,需要安装一个插件 YamlDotNet

YamlDotNet 是开源的,github 可以找到对应的源码。

1.冒号

( : )冒号用于键值对的分隔,冒号后必须跟一个空格

username: admin  
password: 123456

C# 实例:

using System;
using System.Collections.Generic;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;

namespace yaml_test
{
    internal class Program
    {
        static void Main(string[] args)
        {
            string yaml = 
@"
name: zhangsan
";
            var deserializer = new DeserializerBuilder()
                .WithNamingConvention(CamelCaseNamingConvention.Instance)
                .Build();
            var data = deserializer.Deserialize<Dictionary<string, object>>(yaml);

            string name = data["name"] as string;
            Console.WriteLine("名字:{0}", name);

            Console.ReadKey();
        }
    }
}

运行:

2.短横杆

( - )短横杆用于表示列表(数组)的开始

fruits:  
  - Apple  
  - Banana  
  - Cherry

C# 实例:

using System;
using System.Collections.Generic;
using System.Linq;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;

namespace yaml_test
{
    internal class Program
    {
        static void Main(string[] args)
        {
            string yaml =
@"
fruits:  
  - Apple  
  - Banana  
  - Cherry
";
            var deserializer = new DeserializerBuilder()
                .WithNamingConvention(CamelCaseNamingConvention.Instance)
                .Build();
            var data = deserializer.Deserialize<Dictionary<string, object>>(yaml);

            if (data.ContainsKey("fruits") && data["fruits"] is IList<object> fruitsList)
            {
                string[] fruitsArray = fruitsList.Cast<string>().ToArray();
                Console.WriteLine(string.Join(", ", fruitsArray));
            }

            Console.ReadKey();
        }
    }
}

运行:

3.文档分隔符

使用三个连字符(---)表示一个YAML文档的开始,可选地使用三个点(...)表示文档的结束(但在实践中通常省略)。

---  
# 第一个文档  
username: admin  
---  
# 第二个文档  
name: Project A  
description: A new project  
...

4.保留换行符

| 和 > 用于处理多行字符串,其中 | 保留字符串的换行符,而 > 将换行符转换为空格。

poem: |  
  胜日寻芳泗水滨,
  无边光景一时新。
  等闲识得东风面,
  万紫千红总是春。

description: >  
  风和日丽之时游览在泗水之滨,
  无边无际的风光让人耳目一新。
  谁都可以看出春的面貌,万紫千红,
  到处都是百花开放的春景。

C# 实例:

using System;
using System.Collections.Generic;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;

namespace yaml_test
{
    internal class Program
    {
        static void Main(string[] args)
        {
            string yaml =
@"
poem: |  
  胜日寻芳泗水滨,
  无边光景一时新。
  等闲识得东风面,
  万紫千红总是春。

description: >  
  风和日丽之时游览在泗水之滨,
  无边无际的风光让人耳目一新。
  谁都可以看出春的面貌,万紫千红,
  到处都是百花开放的春景。
";
            var deserializer = new DeserializerBuilder()
                .WithNamingConvention(CamelCaseNamingConvention.Instance)
                .Build();
            var data = deserializer.Deserialize<Dictionary<string, object>>(yaml);

            string poem = data["poem"] as string;
            Console.WriteLine(poem);
            Console.WriteLine("===============");
            string description = data["description"] as string;
            Console.WriteLine(description);
            Console.ReadKey();
        }
    }
}

运行:

5.注释

使用井号(#)进行单行注释。

#这是一个注释  
username: admin  
password: 123456  #密码 

三、yaml 语法

1.对象

类似于 C# 中的类

person:  
  name: John Doe  
  age: 30

对应的 C# 对象:

public class person
{
    public string name { get; set; } = "John Doe";
    public int age { get; set; } = 30;
}

将 person 的数据存入一个类中,我发现 yaml 对应的 C# 字段名首个字母改为大写也不会报错

using System;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;

namespace yaml_test
{
    internal class Program
    {
        static void Main(string[] args)
        {
            string yaml =
@"
person:  
  name: John Doe  
  age: 30
";
            var deserializer = new DeserializerBuilder()
                .WithNamingConvention(CamelCaseNamingConvention.Instance)
                .Build();

            var yamlObject = deserializer.Deserialize<YamlRoot>(yaml);

            Console.WriteLine($"Name: {yamlObject.Person.Name}, Age: {yamlObject.Person.Age}");
            Console.ReadKey();
        }
    }
}

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

public class YamlRoot
{
    public Person Person { get; set; }
}

运行:

在读取更复杂的配置文件时,我们完全可以将整个配置文件的数据写入到一个类中

using System;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;

namespace yaml_test
{
    internal class Program
    {
        static void Main(string[] args)
        {
            string yaml =
@"
dog: [dog1, dog2, dog3]
cat: [cat1, cat2]
kunkun: 
  - jige1
  - jige2
  - jige3
person:  
  name: John Doe  
  age: 30
";
            var deserializer = new DeserializerBuilder()
                .WithNamingConvention(CamelCaseNamingConvention.Instance)
                .Build();

            var yamlObject = deserializer.Deserialize<YamlRoot>(yaml);

            Console.WriteLine($"Name: {yamlObject.Person.Name}, Age: {yamlObject.Person.Age}");
            Console.WriteLine(string.Join(",", yamlObject.Kunkun));
            Console.ReadKey();
        }
    }
}

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

public class YamlRoot
{
    public Person Person { get; set; }
    public string[] Dog { get; set; }
    public string[] Cat { get; set; }
    public string[] Kunkun { get; set; }
}

运行:

2.数组

将 yaml 中的数组转换成 C# 中的数组会容易一些,例如:string[],转换为 List<string> 会稍微麻烦一些。

例1:

fruits:  
  - Apple  
  - Banana  
  - Cherry

C# 实例:

using System;
using System.Collections.Generic;
using System.Linq;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;

namespace yaml_test
{
    internal class Program
    {
        static void Main(string[] args)
        {
            string yaml =
@"
fruits:  
  - Apple  
  - Banana  
  - Cherry
";
            var deserializer = new DeserializerBuilder()
                .WithNamingConvention(CamelCaseNamingConvention.Instance)
                .Build();
            var data = deserializer.Deserialize<Dictionary<string, object>>(yaml);

            if (data.ContainsKey("fruits") && data["fruits"] is IList<object> fruitsList)
            {
                string[] fruitsArray = fruitsList.Cast<string>().ToArray();
                Console.WriteLine(string.Join(", ", fruitsArray));
            }

            Console.ReadKey();
        }
    }
}

运行:

3.字符串

字符串的用法在上面的案例出现了多次了,可以加引号,也可以不加,比如:

username: 'admin'
password: 123456

4.布尔

yaml 布尔值可以用多种方式来表示,true,false,yes,no,off

isEnabled: true
isDisabled: false
isActive: yes
isInactive: no
isOn: on
isOff: off

C# 实例:

using System;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;

namespace yaml_test
{
    internal class Program
    {
        static void Main(string[] args)
        {
            string yaml =
@"
isEnabled: true
isDisabled: false
isActive: yes
isInactive: no
isOn: on
isOff: off
";
            var deserializer = new DeserializerBuilder()
            .WithNamingConvention(CamelCaseNamingConvention.Instance)
            .Build();

            var config = deserializer.Deserialize<Config>(yaml);

            Console.WriteLine($"isEnabled: {config.IsEnabled}");
            Console.WriteLine($"isDisabled: {config.IsDisabled}");
            Console.WriteLine($"isActive: {config.IsActive}");
            Console.WriteLine($"isInactive: {config.IsInactive}");
            Console.WriteLine($"isOn: {config.IsOn}");
            Console.WriteLine($"isOff: {config.IsOff}");

            Console.ReadKey();
        }
    }
}

public class Config
{
    public bool IsEnabled { get; set; }
    public bool IsDisabled { get; set; }
    public bool IsActive { get; set; }
    public bool IsInactive { get; set; }
    public bool IsOn { get; set; }
    public bool IsOff { get; set; }
}

5.数值

数值类型包括 int,float 等,比如:

intValue: 123
floatValue: 123.45
doubleValue: 67.89

C# 实例:

dynamic 类型在反序列化时默认被解析为 string,因此要做一些转换

using System;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;

namespace yaml_test
{
    internal class Program
    {
        static void Main(string[] args)
        {
            string yaml =
@"
intValue: 123
floatValue: 123.45
doubleValue: 67.89
";
            var deserializer = new DeserializerBuilder()
            .WithNamingConvention(CamelCaseNamingConvention.Instance)
            .Build();

            // 反序列化 YAML 内容到动态对象
            var data = deserializer.Deserialize<dynamic>(yaml);

            // 读取并转换数值类型
            int intValue = Convert.ToInt32(data["intValue"]);
            float floatValue = Convert.ToSingle(data["floatValue"]);
            double doubleValue = Convert.ToDouble(data["doubleValue"]);

            // 输出结果
            Console.WriteLine($"intValue: {intValue}");
            Console.WriteLine($"floatValue: {floatValue}");
            Console.WriteLine($"doubleValue: {doubleValue}");

            Console.ReadKey();
        }
    }
}

运行:

6.时间

时间的语法可以和字符串一样的使用,读取字符串后,直接转换为 DateTime 就行了

C# 实例:

dynamic 类型在反序列化时默认被解析为 string

using System;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;

namespace yaml_test
{
    internal class Program
    {
        static void Main(string[] args)
        {
            string yaml =
@"
time: 2024/7/22 17:33:30
";
            var deserializer = new DeserializerBuilder()
            .WithNamingConvention(CamelCaseNamingConvention.Instance)
            .Build();

            var data = deserializer.Deserialize<dynamic>(yaml);
            string sTime = data["time"];
            DateTime dateTime;
            if (DateTime.TryParse(sTime, out dateTime))
            {
                Console.WriteLine(dateTime);
            }

            Console.ReadKey();
        }
    }
}

运行:

结束

如果这个帖子对你有用,欢迎 关注 + 点赞 + 留言,谢谢

end

相关推荐

  1. Vue中.env文件配置和注意事项

    2024-07-22 22:12:01       31 阅读
  2. mybatis xml 文件 sql include

    2024-07-22 22:12:01       50 阅读
  3. ffmpeg 从视频文件抓取图片 (帧)

    2024-07-22 22:12:01       46 阅读
  4. ffmpeg 从视频文件抓取图片 (帧)

    2024-07-22 22:12:01       47 阅读
  5. python中requirements.txt文件

    2024-07-22 22:12:01       21 阅读
  6. Redis服务器配置文件配置

    2024-07-22 22:12:01       54 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-22 22:12:01       52 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-22 22:12:01       54 阅读
  3. 在Django里面运行非项目文件

    2024-07-22 22:12:01       45 阅读
  4. Python语言-面向对象

    2024-07-22 22:12:01       55 阅读

热门阅读

  1. 在Spring中获取Bean的各种方式

    2024-07-22 22:12:01       13 阅读
  2. AWS认证SAA-C03每日一题

    2024-07-22 22:12:01       12 阅读
  3. python 中的 pprint 和 print有什么区别?

    2024-07-22 22:12:01       15 阅读
  4. 优化ifelse语句

    2024-07-22 22:12:01       16 阅读