我想知道Josh Close的CsvHelper是否有任何配置我缺少将值转换为null。我是这个库的忠实粉丝,但我一直认为应该有某种配置让它知道你的文件中什么值代表NULL。一个例子是一个值为“NA”,“EMPTY”,“NULL”等的列。我确信我可以创建自己的TypeConverter,但我希望有一个更简单的选项来设置配置中的某个位置对于我遇到的文件,这往往相当普遍。
是否有相对容易的配置设置?
我在CsvHelper.TypeConversion命名空间中找到了TypeConversion,但我不确定在哪里应用这样的东西或正确用法的例子:
new NullableConverter(typeof(string)).ConvertFromString(new TypeConverterOptions(), "NA")
我也在使用最新版本2.2.2
谢谢!
答案 0 :(得分:13)
CsvHelper绝对可以处理可空类型。如果空白列被视为null,则无需滚动自己的TypeConverter。对于我的示例,我假设您正在使用用户定义的流畅映射。
您需要做的第一件事是为您的Nullable类型构造一个CsvHelper.TypeConverter
对象。请注意,我将使用int
,因为默认情况下字符串允许空值。
public class MyClassMap : CsvClassMap<MyClass>
{
public override CreateMap()
{
CsvHelper.TypeConversion.NullableConverter intNullableConverter = new CsvHelper.TypeConversion.NullableConverter(typeof(int?));
Map(m => m.number).Index(2).TypeConverter(intNullableConverter);
}
}
接下来是在CsvReader对象上设置属性以允许空白列和&amp;自动修剪你的领域。我个人喜欢在构建CsvConfiguration
对象之前创建一个包含所有设置的CsvReader
对象。
CsvConfiguration csvConfig = new CsvConfiguration();
csvConfig.RegisterClassMap<MyClassMap>();
csvConfig.WillThrowOnMissingField = false;
csvConfig.TrimFields = true;
然后,您可以调用myReader = new CsvReader(stream, csvConfig)
来构建CsvReader
对象。
如果您需要定义null的值,例如"NA" == null
,那么您将需要推送自己的CsvHelper.TypeConversion
类。我建议您扩展NullableConverter
类来执行此操作并覆盖构造函数和ConvertFromString
方法。使用空值作为null确实是你最好的选择。
答案 1 :(得分:12)
我认为在过去的七年和十三个版本中,有一段时间以来,有人问这个问题,而无需扩展自定义类型映射类的选择,例如:
csvReader.Configuration.TypeConverterOptionsCache.GetOptions<string>().NullValues.Add("NULL");
csvReader.Configuration.TypeConverterOptionsCache.GetOptions<DateTime?>().NullValues.AddRange(new[] { "NULL", "0" });
csvReader.Configuration.TypeConverterOptionsCache.GetOptions<int?>().NullValues.Add("NULL");
csvReader.Configuration.TypeConverterOptionsCache.GetOptions<bool>().BooleanFalseValues.Add("0");
csvReader.Configuration.TypeConverterOptionsCache.GetOptions<bool>().BooleanTrueValues.Add("1");
答案 2 :(得分:0)
我使用了“ ConvertUsing” ...
public class RecordMap : CsvHelper.Configuration.ClassMap<Record>
{
public RecordMap()
{
AutoMap();
Map(m => m.TransactionDate).ConvertUsing( NullDateTimeParser );
Map(m => m.DepositDate).ConvertUsing( NullDateTimeParser );
}
public DateTime? NullDateTimeParser(IReaderRow row)
{
//"CurrentIndex" is a bit of a misnomer here - it's the index of the LAST GetField call so we need to +1
//https://github.com/JoshClose/CsvHelper/issues/1168
var rawValue = row.GetField(row.Context.CurrentIndex+1);
if (rawValue == "NULL")
return null;
else
return DateTime.Parse(rawValue);
}
}