I'm currently trying to parse a value from a csv file that is a boolean. We've noticed that the value will successfully parse Yes and Y (in any case) but will not parse No and N
I'm mapping the value in the classmap like this:
Map(m => m.Enabled).Name("Enabled").TypeConverterOption(false, string.Empty);
Is there a reason why this would read Yes but not No and is there a way to add the ability to parse no?
In version 4.0.3, this works.
void Main()
{
    using (var stream = new MemoryStream())
    using (var writer = new StreamWriter(stream))
    using (var reader = new StreamReader(stream))
    using (var csv = new CsvReader(reader))
    {
        writer.WriteLine("Id,Name,IsSomething");
        writer.WriteLine("1,one,Yes");
        writer.WriteLine("2,two,Y");
        writer.WriteLine("3,three,No");
        writer.WriteLine("4,four,N");
        writer.Flush();
        stream.Position = 0;
        csv.Configuration.RegisterClassMap<TestMap>();
        csv.GetRecords<Test>().ToList().Dump();
    }
}
public class Test
{
    public int Id { get; set; }
    public string Name { get; set; }
    public bool IsSomething { get; set; }
}
public sealed class TestMap : ClassMap<Test>
{
    public TestMap()
    {
        Map(m => m.Id);
        Map(m => m.Name);
        Map(m => m.IsSomething)
            .TypeConverterOption.BooleanValues(true, true, "Yes", "Y")
            .TypeConverterOption.BooleanValues(false, true, "No", "N");
    }
}
In version 2.16.3 this works.
void Main()
{
    using (var stream = new MemoryStream())
    using (var writer = new StreamWriter(stream))
    using (var reader = new StreamReader(stream))
    using (var csv = new CsvReader(reader))
    {
        writer.WriteLine("Id,Name,IsSomething");
        writer.WriteLine("1,one,Yes");
        writer.WriteLine("2,two,Y");
        writer.WriteLine("3,three,No");
        writer.WriteLine("4,four,N");
        writer.Flush();
        stream.Position = 0;
        csv.Configuration.RegisterClassMap<TestMap>();
        csv.GetRecords<Test>().ToList().Dump();
    }
}
public class Test
{
    public int Id { get; set; }
    public string Name { get; set; }
    public bool IsSomething { get; set; }
}
public sealed class TestMap : CsvClassMap<Test>
{
    public TestMap()
    {
        Map(m => m.Id);
        Map(m => m.Name);
        Map(m => m.IsSomething)
            .TypeConverterOption(true, "Yes", "Y")
            .TypeConverterOption(false, "No", "N");
    }
}
As an extension method to make the usage a little easier.
Map(x => x.IsActive).Name("Active").WithExtendedBooleanValues();
Tested on v15, but I'm sure it works well before then.
namespace CsvHelper.Configuration
{
    public static class MemberMapExtensions
    {
        /// <summary>
        /// Adds "y", "yes" and "set to yes" and the "no" equivalents to the list of accepted boolean values
        /// for this member map.
        /// </summary>
        public static MemberMap<TClass, TMember> WithExtendedBooleanValues<TClass, TMember>(
            this MemberMap<TClass, TMember> memberMap)
        {
            memberMap
                // Note: It's case insensitive
                // https://github.com/JoshClose/CsvHelper/blob/master/src/CsvHelper/TypeConversion/BooleanConverter.cs
                .TypeConverterOption.BooleanValues(true, clearValues: false, "y", "yes", "set to yes")
                .TypeConverterOption.BooleanValues(false, clearValues: false, "n", "no", "set to no");
            return memberMap;
        }
    }
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With