Vivek Nuna
Vivek Nuna

Reputation: 1

How to handle empty column in parsing with CsvHelper?

I have a CSV file, I'm trying to parse it, But getting the below error on int datatype column.In the file, I'm passing the blank or empty value for this column.

[AutoMap(typeof(Test))]
[FileEntity("Test")]
public class TestFileEntity : BaseFileEntity
{
    [CsvFileColumn(1)]
    public int TestId { get; set; }
}

public IEnumerable<BaseFileEntity> Parse(Stream masterData, Type entityType, out IEnumerable<MasterDataFileParserError> errors)
{
    var list = new List<BaseFileEntity>();
    var errorList = new List<MasterDataFileParserError>();

    try
    {
        using (var reader = new StreamReader(masterData))
        {
            var parser = new CsvReader(reader, new CsvHelper.Configuration.Configuration
            {
                HasHeaderRecord = true,
                HeaderValidated = null,
                MissingFieldFound = null
            });

            list.AddRange(parser.GetRecords(entityType).Cast<BaseFileEntity>());
        }
    }
    catch (Exception ex)
    {
        if (ex.Data == null || ex.Data.Count == 0)
        {
            errorList.Add(new MasterDataFileParserError
            {
                Error = ex.Message,
                Description = ex.ToString()
            });
        }
        else
        {
            foreach (var key in ex.Data.Keys)
            {
                errorList.Add(new MasterDataFileParserError
                {
                    Error = ex.Message,
                    Description = $"{key}: {ex.Data[key]}"
                });
            }
        }
    }

    errors = errorList;

    return list;
}

Exception in this line: list.AddRange(parser.GetRecords(entityType).Cast<BaseFileEntity>());

Error:

An error has occurred while parsing 'xyz.csv' file for 'Test' entity: '[{"Error":"The conversion cannot be performed.\r\n Text: ''\r\n
MemberType: System.Int32\r\n TypeConverter: 'CsvHelper.TypeConversion.Int32Converter'","Description":"CsvHelper.TypeConversion.TypeConverterException: The conversion cannot be performed.\r\n Text: ''\r\n MemberType: System.Int32\r\n TypeConverter: 'CsvHelper.TypeConversion.Int32Converter'\r\n at CsvHelper.Configuration.Configuration.<>c.<.ctor>b__148_4(CsvHelperException exception)\r\n at CsvHelper.CsvReader.d__65.MoveNext()\r\n at System.Linq.Enumerable.d__341.MoveNext()\r\n at System.Collections.Generic.List1.AddEnumerable(IEnumerable1 enumerable)\r\n at System.Collections.Generic.List1.InsertRange(Int32 index, IEnumerable1 collection)\r\n at Nec.Stanchion.Business.MasterDataFiles.Handling.MasterDataFileParser.Parse(Stream masterData, Type entityType, IEnumerable1& errors) in xyz.cs file"}]'.

The reason is very clear, that blank or empty string is not compatible with int datatype, so there has to be some way to allow empty or null value with int datatype column value.

CsvHelper Version=6.0.0.0

Upvotes: 7

Views: 16097

Answers (2)

adi ben
adi ben

Reputation: 489

I also had this problem, of null/ other problematic values that are not excepted in double or decimal objects

The best solution I've found goes like this:

   //first inject the class map
   CsvReader csv = new CsvReader(new 
   StreamReader(file.OpenReadStream()));
   csv.Configuration.RegisterClassMap<SomeEntityClassMap>();
   var records = csv.GetRecords<SomeEntity>().ToList();
 
public class SomeEntityClassMap : ClassMap<SomeEntity>
{
    public SomeEntityClassMap()
    {
        //use the converter on double or decimal types
        Map(x => x.Price).TypeConverter<DoubleConverter>();
        Map(x => x.Cost).TypeConverter<DoubleConverter>();
    }
}

public class DoubleConverter : DefaultTypeConverter
{
    public override object ConvertFromString(string text, IReaderRow row, MemberMapData memberMapData)
    {
        if(double.TryParse(text, out var result))
            return result;

        return 0;
    }
}

Upvotes: 5

Matheus Lacerda
Matheus Lacerda

Reputation: 6007

I'm using CsvHelper 6.1.0 in my current project, just tested a use case similar to yours, int field in blank in the csv file, and had no problem. This is the code I'm using, hope it helps:

        CsvReader csv = new CsvReader(new StreamReader(file.OpenReadStream()));
        csv.Configuration.RegisterClassMap<PessoaCSVMap>();
        csv.Configuration.Delimiter = ";";
        csv.Configuration.HeaderValidated = null;
        csv.Configuration.MissingFieldFound = null;
        List<Pessoas> pessoas = csv.GetRecords<Pessoas>().ToList();

public sealed class PessoaCSVMap : ClassMap<Pessoas>
{
    public PessoaCSVMap()
    {
        Map(m => m.Nome).Name("Nome", "Name");
        ... etc
    }
}

Upvotes: 7

Related Questions