Добавление обнаруживаемых значений Nullable в CsvHelper
Мне было интересно, если CsvHelper Джоша Клоуз имеет что-то в конфигурации, я пропускаю, чтобы перевести значения в ноль. Я большой поклонник этой библиотеки, но я всегда думал, что должна быть какая-то конфигурация, чтобы она знала, какие значения представляют NULL в вашем файле. Примером может служить столбец со значениями "NA", "EMPTY", "NULL" и т. Д. Я уверен, что мог бы создать свой собственный TypeConverter, но я надеялся, что будет более простой вариант для установки где-нибудь в конфигурации как это обычно встречается в файлах, с которыми я сталкиваюсь.
Есть ли настройки конфигурации, чтобы сделать это относительно легко?
Я нашел TypeConversion в пространстве имен CsvHelper.TypeConversion, но не уверен, где применить что-то подобное или пример правильного использования:
new NullableConverter(typeof(string)).ConvertFromString(new TypeConverterOptions(), "NA")
Я также использую последнюю версию 2.2.2
Спасибо!
1 ответ
CsvHelper может обрабатывать типы, допускающие обнуление. Вам не нужно накатывать свой собственный TypeConverter, если пустой столбец считается пустым. Для моих примеров я предполагаю, что вы используете пользовательские беглые отображения.
Первое, что вам нужно сделать, это построить CsvHelper.TypeConverter
объект для ваших Nullable типов. Обратите внимание, что я собираюсь использовать 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, чтобы разрешить пустые столбцы и автоматически обрезать поля. Лично нравится делать это, создавая CsvConfiguration
объект со всеми моими настройками до создания моего CsvReader
объект.
CsvConfiguration csvConfig = new CsvConfiguration();
csvConfig.RegisterClassMap<MyClassMap>();
csvConfig.WillThrowOnMissingField = false;
csvConfig.TrimFields = true;
Тогда вы можете позвонить myReader = new CsvReader(stream, csvConfig)
построить CsvReader
объект.
Если вам нужно определить значения для нуля, такие как "NA" == null
тогда вам нужно будет свернуть свой собственный CsvHelper.TypeConversion
учебный класс. Я рекомендую вам продлить NullableConverter
класс, чтобы сделать это и переопределить как конструктор и ConvertFromString
метод. Использование пустых значений в качестве нулевого значения действительно является лучшим выбором.
Я думаю, что когда-то за последние семь лет и в тринадцати версиях с тех пор, как был задан этот вопрос, варианты для этого без расширения класса карты пользовательского типа, например:
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");
Я использовал "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);
}
}