使用CSVHelper解析含JSON数据列的CSV文件遇到的问题
解决CSVHelper解析包含未转义JSON列的CSV文件问题
你的问题根源在于CSV文件中JSON字段的双引号未正确转义,导致CSVHelper无法识别整个JSON字符串为单个字段,进而将JSON内部的逗号误判为CSV分隔符。以下是两种可行的解决方法:
方案1:修复CSV格式(推荐)
如果可以控制CSV的生成逻辑,确保JSON字段内的双引号按CSV规范转义。标准CSV中,字段内的双引号需要用双引号重复转义,修正后的CSV内容如下:
id1,4000,"{""red"":""#f00"",""green"":""#0f0"",""blue"":""#00f""}",color_pattern1 id2,300,"{""magenta"":""#f0f"",""yellow"":""#ff0"",""black"":""#000""}",color_pattern2
或者使用反斜杠转义(需配合CSVHelper配置):
id1,4000,"{\"red\":\"#f00\",\"green\":\"#0f0\",\"blue\":\"#00f\"}",color_pattern1 id2,300,"{\"magenta\":\"#f0f\",\"yellow\":\"#ff0\",\"black\":\"#000\"}",color_pattern2
对应调整CSVHelper配置:
var config = new CsvConfiguration(CultureInfo.InvariantCulture) { HasHeaderRecord = false, // 若用反斜杠转义,需添加以下配置 // Escape = '\\' };
修改后你的原有解析代码即可正常工作,CSVHelper会自动识别完整的JSON字段。
方案2:自定义解析逻辑(无法修改CSV时)
如果无法调整CSV生成规则,可通过自定义逻辑手动识别JSON字段的边界。
方法A:逐行手动拆分字段
直接读取每行文本,根据引号和JSON结构拆分字段:
TextReader tr = new StreamReader(blobContent); string line; while ((line = tr.ReadLine()) != null) { int firstQuote = line.IndexOf('"'); int lastQuote = line.LastIndexOf('"'); if (firstQuote == -1 || lastQuote == -1 || firstQuote >= lastQuote) continue; // 拆分四个字段 int firstComma = line.IndexOf(','); int secondComma = line.IndexOf(',', firstComma + 1); int lastComma = line.IndexOf(',', lastQuote + 1); var record = new CSVData { Id = line.Substring(0, firstComma), Intensity = line.Substring(firstComma + 1, secondComma - firstComma - 1), JsonData = line.Substring(firstQuote + 1, lastQuote - firstQuote - 1), ColourPatternId = line.Substring(lastComma + 1) }; Console.WriteLine($"JSON Data: {record.JsonData}"); Console.WriteLine($" Colour Pattern ID: {record.ColourPatternId}"); }
方法B:自定义CSVHelper转换器
通过TypeConverter处理JSON字段的拼接:
public class JsonFieldConverter : StringConverter { public override object ConvertFromString(string text, IReaderRow row, MemberMapData memberMapData) { var sb = new StringBuilder(text); int braceCount = text.Count(c => c == '{') - text.Count(c => c == '}'); // 持续读取字段直到JSON括号闭合 while (braceCount > 0 && row.Parser.Read()) { string nextField = row.Parser.Record[row.Parser.Index]; sb.Append(",").Append(nextField); braceCount += nextField.Count(c => c == '{') - nextField.Count(c => c == '}'); } return sb.ToString(); } }
在CSVData类的JsonData属性上绑定转换器:
public class CSVData { [Index(0)] public string Id { get; set; } [Index(1)] public string Intensity { get; set; } [Index(2)] [TypeConverter(typeof(JsonFieldConverter))] public string JsonData { get; set; } [Index(3)] public string ColourPatternId { get; set; } }
最后恢复CSVHelper配置(不要设置BadDataFound = null):
var config = new CsvConfiguration(CultureInfo.InvariantCulture) { HasHeaderRecord = false }; using (var csv = new CsvReader(new StreamReader(blobContent), config)) { foreach (var r in csv.GetRecords<CSVData>()) { Console.WriteLine($"JSON Data: {r.JsonData}"); Console.WriteLine($" Colour Pattern ID: {r.ColourPatternId}"); } }
内容的提问来源于stack exchange,提问作者blank_stare
相关产品推荐
相关产品推荐

