CsvHelper CsvClassMapを使わない方法

「CsvHelperって、CsvClassMapを使わないとマッピングできないよね?」
「CsvHelperのマッピングって、もっと簡単にできないのかな?」

こんなことを悩んでいませんか?
こういった疑問に答えます。

今日は「CsvHelperでCsvClassMapを使わないマッピング方法」について紹介します。

 

コピペで使えるサンプルコードという近道

現場レベルのCsvHelperの実装サンプルを作りました。
CSVデータの取得から、入力チェック、モデル変換まで網羅しています。

5つのシステムで実証したコピペで使い回せる実装法
» 【CsvHelper マスター講座】を見る

目次

CsvHelper.Configuration.CsvClassMapとは?

どう使うの?

CsvHelper.Configuration.CsvClassMapを継承したマッピング用クラスを作成してマッピングをします。

※バージョン 15.0.0は、CsvHelper.Configuration.ClassMapです。クラス名が変わっています。

CsvClassMapを使う方法

検証したCsvHelperは、バージョン 15.0.0です。

テストデータ

伊藤,東京都
佐藤,千葉県

ソース

public class Test
{
    public void Main()
    {
        var members = CsvHelperPerformer.GetRecords<Member, MemberMapper>(@"C:\csv\test.csv");
        foreach (var member in members)
        {
            Console.WriteLine($"Name:{member.Name}  Address:{member.Address}");
        }
    }
}


public class CsvHelperPerformer
{
    /// <summary>
    /// ファイルを読み込む
    /// </summary>
    /// <typeparam name="TModel">変換するクラス</typeparam>
    /// <typeparam name="TMapper">ファイル</typeparam>
    /// <param name="path"></param>
    /// <returns></returns>
    public static List<TModel> GetRecords<TModel, TMapper>(string path) where TMapper : CsvHelper.Configuration.ClassMap
    {
        using (var reader = new StreamReader(path, Encoding.GetEncoding("SHIFT_JIS")))
        using (var csv = new CsvReader(reader, new CultureInfo("ja-JP", false)))
        {
            csv.Configuration.HasHeaderRecord = false;
            csv.Configuration.RegisterClassMap<TMapper>();

            return csv.GetRecords<TModel>().ToList();
        }
    }
}


/// <summary>
/// データ格納用クラス
/// </summary>
public class Member
{
    public string Name { get; set; }
    public string Address { get; set; }
}


/// <summary>
/// マッピング用クラス
/// </summary>
public class MemberMapper : CsvHelper.Configuration.ClassMap<Member> // ←データ格納用クラスを指定
{
    public MemberMapper()
    {
        Map(x => x.Name).Index(0); // x.Xxxxには、Memberのメンバを設定。.Index(X)には、Csvのインデックスを設定
        Map(x => x.Address).Index(1);
    }
}
    
// 【実行結果】
// Name:伊藤  Address:東京都
// Name:佐藤  Address:千葉県

Genericsを使用して汎用的にしたソースです。

呼び出し側のCsvHelperPerformer.GetRecords<Member, MemberMapper>を変えることでクラスを汎用的に使えるようにしています。

ポイントをまとめておきます。

ポイント

  • データ格納用のクラスとマッピング用クラスを作ります。
  • マッピング用クラスは、CsvHelper.Configuration.ClassMap<Member>とデータ格納クラスを指定して継承します。
  • マッピングは、Map(x => x.Name).Index(0);で指定します。

    • x.Xxxxには、データ格納用クラスのメンバを設定します。
    • .Index(X)には、Csvのインデックスを設定します。
    • ※この場合は、データ格納クラスのNameに、Csvのインデックス0のデータを格納するという意味になります。

マッピング用クラスを作るのも一つや二つならいいけど、何個も作るとなるとけっこう面倒です。

マッピングクラスを作らない方が、ずっと簡単です。

次に、CsvClassMap(=マッピング用クラス)を使わないマッピングの方法を紹介します。

CsvClassMapを使わない方法

テストデータ

先ほどのと同じデータです。

ソース

public class Test
{
    public void Main()
    {
        var members = CsvHelperPerformer.GetRecords<Member>(@"C:\csv\test.csv");
        foreach (var member in members)
        {
            Console.WriteLine($"Name:{member.Name}  Address:{member.Address}");
        }
    }
}


public class CsvHelperPerformer
{
    /// <summary>
    /// ファイルを読み込む
    /// </summary>
    /// <typeparam name="TModel">変換するクラス</typeparam>
    /// <param name="path"></param>
    /// <returns></returns>
    public static List<TModel> GetRecords<TModel>(string path)
    {
        using (var reader = new StreamReader(path, Encoding.GetEncoding("SHIFT_JIS")))
        using (var csv = new CsvReader(reader, new CultureInfo("ja-JP", false)))
        {
            csv.Configuration.HasHeaderRecord = false;
            //csv.Configuration.RegisterClassMap<TMapper>(); //不要です。

            return csv.GetRecords<TModel>().ToList();
        }
    }
}


/// <summary>
/// データ格納用クラス
/// </summary>
public class Member
{
    [Index(0)] // ←マッピング用クラスのかわりにインデックスを指定する
    public string Name { get; set; }

    [Index(1)]
    public string Address { get; set; }
}
    
// 【実行結果】
// Name:伊藤  Address:東京都
// Name:佐藤  Address:千葉県

マッピング用クラスがなくなって、csv.Configuration.RegisterClassMap<TMapper>(); の設定が必要なくなります。

GetRecordsメソッドの記述もシンプルになって、呼び出し側もパラメータが減ってスッキリさせることができました。

ポイントのおさらいです。

ポイント

  • データ格納用のクラスだけを作ります。マッピング用クラスは不要です。
  • マッピングは、[Index(0)]で指定します。

    • [Index(x)]には、Csvのインデックスを設定します。
    • ※この場合は、データ格納クラスのNameに、Csvのインデックス0のデータを格納するという意味になります。

まとめ

CsvHelperでCsvClassMapを使わないマッピング方法について紹介しました。

マッピングで特定の値をnullとして扱う方法についても書いています。興味がある方は「マッピングで特定の値をnullとして扱う方法」の記事をどうぞ。

DateTime型(日付型)に変換してマッピングする方法について知りたい方は「CsvHelper DateTime型(日付型)に変換してマッピングする方法」をどうぞ。

なかなか情報が少ないですが、CsvHelperは使いこなせれば便利だと思います。

他にも知らない設定や使い方があるんじゃないかと思います。興味がある方は「CsvHelper Configurationの設定」の記事をどうぞ。

こちらの記事も読まれています!


よかったらシェアしてね!
目次
閉じる