Quantcast
Channel: かずきのBlog@hatena
Viewing all articles
Browse latest Browse all 1387

CsvHelper でパースするときに NULL という文字列のセルを null として扱いたい

$
0
0

こんな csv を扱う必要がありまして。

Tanaka,38
Kazuki,NULL
Kazuakix,98
muu,NULL

null が入ってるところには丁寧に文字列で NULL と記載されています。 こういう csv を見るたびにデータ部分に NULL っていう文字列データつっこんだらどうするんだろうと思ってしまう今日この頃です。 今回の例は、数字の列なので、そういういたずらは出来ませんが。

ということで個人的に C# で CSV を扱う時によくつかってる CsvHelper でのやりかたです。

ドキュメント的にはここらへんですね。

joshclose.github.io

joshclose.github.io

ClassMap というクラスを使ってクラスと csv のマッピングをカスタマイズできるのですが、ここで TypeConverter というのをかませることが出来ます。 ということで、今回の場合はこういう TypeConverter を作って…。

class NullableIntConverter : ITypeConverter
{
    publicobject ConvertFromString(string text, IReaderRow row, MemberMapData memberMapData)
    {
        return text == "NULL" ?
            null :
            (int?)int.Parse(text); // 数字じゃないデータきたら潔く死ぬ
    }

    publicstring ConvertToString(objectvalue, IWriterRow row, MemberMapData memberMapData)
    {
        thrownew NotImplementedException(); // 今回は読込だけなので、こっちは実装しない。
    }
}

そして、こんな感じにクラスと ClassMap を作ります。

class Record
{
    publicstring Name { get; set; }
    publicint? Age { get; set; }
}

class RecordMap : ClassMap<Record>
{
    public RecordMap()
    {
        this.AutoMap();
        this.Map(x => x.Age).TypeConverter<NullableIntConverter>();
    }
}

では、さっそく試してみましょう。

namespace CSVHelperLab
{
    class Program
    {
        staticvoid Main(string[] args)
        {
            var csv = @"Tanaka,38Kazuki,NULLKazuakix,98muu,NULL";
            using (var p = new CsvReader(new StringReader(csv)))
            {
                p.Configuration.HasHeaderRecord = false;
                p.Configuration.RegisterClassMap<RecordMap>();
                var records = p.GetRecords<Record>();
                foreach (var record in records)
                {
                    Console.WriteLine($"{record.Name}: {record.Age}");
                }
            }
        }
    }
}

実行するとこうなります。

Tanaka: 38
Kazuki:
Kazuakix: 98
muu:

いい感じですね。


Viewing all articles
Browse latest Browse all 1387

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>