【C#】YAMLファイルの読み込み・書き込み方法

【C#】YAMLファイルの読み込み・書き込み方法

YamlDotNetによるYAMLファイルの読み込み・書き込み方法について記載します。

<確認環境>
Windows10 64bit
Visual Studio 2022
.NET6.0
YamlDotNet v13.0.2

YamlDotNetとは

YamlDotNetはYAMLを取り扱うためのオープンソースのライブラリです。.NET Frameworkおよび.NETCoreで使用できます。ライセンスはMITで提供されます。
https://github.com/aaubry/YamlDotNet

YamlDotNetのインストール

Visual Studio のメニューから[ツール] > [NuGet パッケージマネージャー] > [パッケージマネージャーコンソール] を選択して以下のコマンドを実行します。

Install-Package YamlDotNet

または、[プロジェクト] > [NuGet パッケージ管理] でYamlDotNetを検索してインストールします。
YamlDotNetのインストール

YamlDotNetによるYAMLファイルの読み込み

YAMLファイルを読み込む方法を記載します。

読み込むYAMLファイルの内容
- Name: ピカチュウ
  Abilities:
  - でんきショック
  - ボルテッカー
  Parameter:
    HP: 70
    ATK: 50
    DEF: 20
- Name: イーブイ
  Abilities:
  - たいあたり
  - しっぽをふる
  Parameter:
    HP: 90
    ATK: 30
    DEF: 40

オブジェクトに読み込む

Deserializerクラスを使用してYAMLファイルの内容をデータ格納クラスに読み込みます。以下はYAMLキーとデータ格納クラスのプロパティ名が一致しているときの読み込みです。(YAMLキーと異なるときは「YAMLキーとプロパティ名が異なるときの読み込み」に記載。)

コード
using YamlDotNet.Serialization;

// YAMLファイルの読み込み
using (var reader = new StreamReader(@"C:\work\pokemon.yml", System.Text.Encoding.UTF8))
{
    // Deserializer作成
    var deserializer = new DeserializerBuilder().Build();
    // データ格納リストにYAMLファイルの内容を読み込む
    var pokemons = deserializer.Deserialize<List<Pokemon>>(reader.ReadToEnd());
}

// データ格納クラス
public class Pokemon
{
    public string Name { get; set; }
    public string[] Abilities { get; set; }
    public Parameter Parameter { get; set; }
}
public class Parameter
{
    public int HP { get; set; }
    public int ATK { get; set; }
    public int DEF { get; set; }
}

YamlStreamに読み込む

YAMLファイルの内容をYamalStreamに読み込みます。以下はYamlファイルを読み込んだあとに、ルートノードからイーブイのAbilitiesを特定しています。

コード
using YamlDotNet.RepresentationModel;

using (var input = new StreamReader(@"C:\work\pokemon.yml", System.Text.Encoding.UTF8))
{
    // YamlStreamに読み込み
    var yaml = new YamlStream();
    yaml.Load(input);
    
    // ルートノード取得
    var rootNode = (YamlSequenceNode)yaml.Documents[0].RootNode;
    foreach (var node in rootNode.Children)
    {
        // キー:Nameのノード取得
        var nameNode = (YamlScalarNode)node["Name"];
        if (nameNode.Value == "イーブイ")
        {
            // キー:Abilitiesのノード取得
            var abilitiesNode = (YamlSequenceNode)node["Abilities"];
            foreach (var abilityNode in abilitiesNode)
            {
                // イーブイのAbilitysを出力
                Console.WriteLine(abilityNode);
            }
            break;
        }
    }
}

YamlDotNetによるYAMLファイルの書き込み

Yamlファイルの書き込み方法を記載します。

書き込むYAMLファイルの内容
- Name: ピカチュウ
  Abilities:
  - でんきショック
  - ボルテッカー
  Parameter:
    HP: 70
    ATK: 50
    DEF: 20
- Name: イーブイ
  Abilities:
  - たいあたり
  - しっぽをふる
  Parameter:
    HP: 90
    ATK: 30
    DEF: 40

オブジェクトの書き込み

Serializerクラスを使用してデータ格納クラスの内容をYAMLファイルに書き込みます。YAMLのキーや出力順はデータ格納クラスの内容と同じになります。(キーや出力順を設定する方法は「キー・出力順・コメントの書き込み」に記載。)

コード
using YamlDotNet.Serialization;

// データ作成
var pokemons  = new List<Pokemon>
{
    new Pokemon
    {
        Name = "ピカチュウ",
        Abilities = new[] { "でんきショック", "ボルテッカー" },
        Parameter = new Parameter { HP = 70, ATK = 50, DEF = 20 }
    },
    new Pokemon
    {
        Name = "イーブイ",
        Abilities = new[] { "たいあたり", "しっぽをふる" },
        Parameter = new Parameter { HP = 90, ATK = 30, DEF = 40 }
    }
};

// YAMLファイルの書き込み
using (var writer = new StreamWriter(@"C:\work\pokemon.yml", false, System.Text.Encoding.UTF8))
{
    // Serializer作成
    var serializer = new SerializerBuilder().Build();
    // データリストをStreamWriterに書き込む
    serializer.Serialize(writer, pokemons);
}

// データ格納クラス
public class Pokemon
{
    public string Name { get; set; }
    public string[] Abilities { get; set; }
    public Parameter Parameter { get; set; }
}
public class Parameter
{
    public int HP { get; set; }
    public int ATK { get; set; }
    public int DEF { get; set; }
}

YamlStreamの書き込み

YamlStreamを使用してノードの内容をYAMLファイルに書き込みます。

コード
using YamlDotNet.RepresentationModel;

// ルートノード作成
var rootNode = new YamlSequenceNode(
    new YamlMappingNode(new YamlScalarNode("Name"), new YamlScalarNode("ピカチュウ"))
    {
        {
            "Abilities", new YamlSequenceNode( 
                new YamlScalarNode("でんきショック"),
                new YamlScalarNode("ボルテッカー")
                ) 
        },
        { 
            "Parameter", new YamlMappingNode(
                new YamlScalarNode("HP"), new YamlScalarNode("70"),
                new YamlScalarNode("ATK"), new YamlScalarNode("50"),
                new YamlScalarNode("DEF"), new YamlScalarNode("20")
                )
        }
    },
    new YamlMappingNode(new YamlScalarNode("Name"), new YamlScalarNode("イーブイ"))
    {
        {
            "Abilities", new YamlSequenceNode(
                new YamlScalarNode("たいあたり"),
                new YamlScalarNode("しっぽをふる")
                )
        },
        {
            "Parameter", new YamlMappingNode(
                new YamlScalarNode("HP"), new YamlScalarNode("90"),
                new YamlScalarNode("ATK"), new YamlScalarNode("30"),
                new YamlScalarNode("DEF"), new YamlScalarNode("40")
                )
        }
    }
);

// YAMLファイルの書き込み
using (var writer = new StreamWriter(@"C:\work\pokemon.yml", false, System.Text.Encoding.UTF8))
{
    var doc = new YamlDocument(rootNode);
    var yamlStream = new YamlStream(doc);
    yamlStream.Save(writer, false);
}

YamlMemberAttributeの設定

データ格納プロパティにYamlMemberAttributeを設定してYAMLファイルの読み込み・書き込みを行います。

YAMLキーとプロパティ名が異なるときの読み込み

データ格納クラスのプロパティに属性を設定してYAMLファイルを読み込みます。
・Alias属性:YAMLキーとプロパティをマッピングします。

読み込むYAMLファイルの内容
- 名前: ピカチュウ
  技:
  - でんきショック
  - ボルテッカー
  パラメータ:
    体力: 70
    攻撃力: 50
    防御力: 20
- 名前: イーブイ
  技:
  - たいあたり
  - しっぽをふる
  パラメータ:
    体力: 90
    攻撃力: 30
    防御力: 40

コード
using YamlDotNet.Serialization;

// YAMLファイルの読み込み
using (var reader = new StreamReader(@"C:\work\pokemon.yml", System.Text.Encoding.UTF8))
{
    // Deserializer作成
    var deserializer = new DeserializerBuilder().Build();
    // データ格納リストにYamlファイルの内容を読み込む
    var pokemons = deserializer.Deserialize<List<Pokemon>>(reader.ReadToEnd());
}

// データ格納クラス
// Alias属性でYAMLキーを定義してマッピング
public class Pokemon
{
    [YamlMember(Alias = "名前")]
    public string Name { get; set; }
    [YamlMember(Alias = "技")]
    public string[] Abilities { get; set; }
    [YamlMember(Alias = "パラメータ")]
    public Parameter Parameter { get; set; }
}
public class Parameter
{
    [YamlMember(Alias = "体力")]
    public int HP { get; set; }
    [YamlMember(Alias = "攻撃力")]
    public int ATK { get; set; }
    [YamlMember(Alias = "防御力")]
    public int DEF { get; set; }
}

キー・出力順・コメントの書き込み

データ格納クラスのプロパティに属性を設定してYAMLファイルに書き込みます。
・Alias属性:YAMLキーとプロパティをマッピングします。
・Order属性:プロパティの出力順を設定します。
・Description属性:Yamlのコメントを設定します。

書き込むYAMLファイルの内容
- 名前: ピカチュウ
  パラメータ:
    # HP:体力  ATK:攻撃力  DEF:防御力
    HP: 70
    ATK: 50
    DEF: 20
  技:
  - でんきショック
  - ボルテッカー
- 名前: イーブイ
  パラメータ:
    # HP:体力  ATK:攻撃力  DEF:防御力
    HP: 90
    ATK: 30
    DEF: 40
  技:
  - たいあたり
  - しっぽをふる

コード
using YamlDotNet.Serialization;

// データ作成
var pokemons  = new List<Pokemon>
{
    new Pokemon
    {
        Name = "ピカチュウ",
        Abilities = new[] { "でんきショック", "ボルテッカー" },
        Parameter = new Parameter { HP = 70, ATK = 50, DEF = 20 }
    },
    new Pokemon
    {
        Name = "イーブイ",
        Abilities = new[] { "たいあたり", "しっぽをふる" },
        Parameter = new Parameter { HP = 90, ATK = 30, DEF = 40 }
    }
};

// YAMLファイルの書き込み
using (var writer = new StreamWriter(@"C:\work\pokemon.yml", false, System.Text.Encoding.UTF8))
{
    // Serializer作成
    var serializer = new SerializerBuilder().Build();
    // データリストをStreamWriterに書き込む
    serializer.Serialize(writer, pokemons);
}

// データ格納クラス
// Alias属性でキー、Order属性で出力順を定義
public class Pokemon
{
    [YamlMember(Alias = "名前", Order = 1)]
    public string Name { get; set; }
    [YamlMember(Alias = "技", Order = 3)]
    public string[] Abilities { get; set; }
    [YamlMember(Alias = "パラメータ", Order = 2)]
    public Parameter Parameter { get; set; }
}

public class Parameter
{
    // Description属性でコメント定義
    [YamlMember(Description = "HP:体力  ATK:攻撃力  DEF:防御力")]
    public int HP { get; set; }
    public int ATK { get; set; }
    public int DEF { get; set; }
}


Next Post Previous Post