-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
I am experiencing this on version 33.0.1, but I don't see anything about this in the changelog for the latest version, so I believe it's likely still present there too. Please correct me if I am wrong, or if there's any preferred workaround for this issue.
Describe the bug
When reading CSV data into C# record types declared in typical shorthand with positional constructors and optional fields, ClassMap objects cannot properly use Map(m => m.OptionalProperty).Ignore() to stop requiring that those fields be present in CSV files. The Ignore = true value successfully makes it into the ClassMap's MemberMaps, but not its ParameterMaps for each such OptionalProperty. Therefore, when CsvReader.ValidateHeader is invoked in the process of reading a CSV without headers for the ignored fields, the absent fields that should be ignored are counterintuitively still added to invalidHeaders and we end up with a HeaderValidationException. This is quite inconvenient for my use case, and seems like it may well be unintentional behavior.
This issue can be suppressed by placing [Ignore] before the names of the affected fields in the record type's primary constructor, but this is not an acceptable workaround for me, as I want certain fields to be ignored in certain contexts and required in other contexts (and I'd think this would be exactly what ClassMaps are intended to allow us to do).
To Reproduce
example.csv:
RequiredStr,RequiredInt
"hello",2
example.cs:
...
public record CsvClass(
string RequiredStr,
int RequiredInt,
string? OptionalStr = null);
private sealed class ExampleMap : ClassMap<CsvClass>
{
public ExampleMap()
{
AutoMap(CultureInfo.InvariantCulture);
Map(m => m.OptionalStr).Ignore();
}
}
public List<CsvClass> ReadFromCsvExample()
{
using var streamReader = new StreamReader(File.Open(".../example.cs", FileMode.Open));
using var csvReader = new CsvReader(streamReader, CultureInfo.InvariantCulture);
csvReader.Context.RegisterClassMap<ExampleMap>();
return csvReader.GetRecords<CsvClass>().ToList();
}
Expected behavior
Calling Map(m => m.x).Ignore() in the constructor of a ClassMap<T> object, where T is any record object with an optional parameter x in its default constructor, should properly cause the property x to be ignored when it is absent from a CSV, and the default value supplied for it to be used in the main constructor for T.