C#解析含逗号金额列CSV转JSON 避免金额字段截断错误
问题根源
原有代码直接通过string.Split(',')拆分每行内容的逻辑不符合RFC 4180 CSV规范,无法识别双引号包裹的字段边界,当字段内部包含逗号时(如示例中的"$2,651.98"),会错误拆分字段,最终导致值截断、字段错位。
解决方案
不推荐手动编写CSV分割逻辑:CSV格式除内嵌逗号场景外,还存在双引号转义、字段内嵌换行、前后空白符处理等大量边界情况,手动实现极易遗漏场景触发解析异常,优先选择成熟解析方案。
方案1:使用CsvHelper组件实现(生产环境推荐)
CsvHelper是C#生态中广泛使用的CSV处理组件,默认遵循RFC 4180标准,可自动识别双引号包裹的内嵌逗号字段,搭配Newtonsoft.Json可快速完成转换,稳定性高。
- 将CsvHelper组件引入项目
- 参考实现代码如下:
using CsvHelper; using CsvHelper.Configuration; using Newtonsoft.Json; using System.Globalization; using System.IO; // 配置CSV解析规则 var config = new CsvConfiguration(CultureInfo.InvariantCulture) { HasHeaderRecord = true, // 指定首行为表头 TrimOptions = TrimOptions.Trim, // 自动去除字段前后多余空白 Mode = CsvMode.RFC4180 // 按标准CSV格式解析,自动处理引号包裹字段 }; // 读取CSV字符串内容 using (var reader = new StringReader(csvResponseData)) using (var csv = new CsvReader(reader, config)) { // 自动映射表头与字段值,读取为结构化对象 var records = csv.GetRecords<dynamic>().ToList(); // 序列化为JSON返回 return JsonConvert.SerializeObject(records); }
该方案可完整识别示例中"$2,651.98"、"$3,252.97"这类带逗号的金额字段,不会出现拆分错误。
方案2:无第三方依赖的轻量实现
如果不希望引入外部组件,可自行实现符合基础CSV规范的字段分割方法,替换原有Split(',')逻辑即可。
首先实现单行CSV字段解析方法:
private static List<string> ParseCsvLine(string line) { var fields = new List<string>(); var currentField = new StringBuilder(); bool inQuotedField = false; for (int i = 0; i < line.Length; i++) { char c = line[i]; if (c == '"') { // 处理双引号转义:两个连续双引号代表字段内的一个双引号字符 if (inQuotedField && i < line.Length - 1 && line[i + 1] == '"') { currentField.Append('"'); i++; } else { // 切换引号包裹状态 inQuotedField = !inQuotedField; } } else if (c == ',' && !inQuotedField) { // 仅当不在引号包裹范围内时,逗号才作为字段分隔符 fields.Add(currentField.ToString().Trim('\\').Trim()); currentField.Clear(); } else { currentField.Append(c); } } // 追加最后一个字段 fields.Add(currentField.ToString().Trim('\\').Trim()); return fields; }
再修改原有解析逻辑,将所有直接调用Split(',')的位置替换为上述方法:
var lines = csvResponseData.Split('\n'); // 解析表头 var properties = ParseCsvLine(lines[0]); var listObjResult = new List<Dictionary<string, string>>(); for (int i = 1; i < lines.Length; i++) { if (lines[i].Length > 5) { var objResult = new Dictionary<string, string>(); // 解析当前行字段 var lineFields = ParseCsvLine(lines[i]); for (int j = 0; j < properties.Count; j++) { if (j < lineFields.Count) { objResult.Add(properties[j], lineFields[j]); } } listObjResult.Add(objResult); } else { break; } } return JsonConvert.SerializeObject(listObjResult);
注意:轻量实现仅覆盖常规CSV场景,如果文件存在字段内嵌换行、特殊转义字符等复杂格式,优先选择成熟组件方案。
解析效果验证
针对给出的CSV示例,修正后可正确识别所有字段,无截断问题:
- textbox69字段完整值为
$2,651.98 - textbox71字段完整值为
$3,252.97 - 其余无特殊字符的字段解析结果与原有逻辑一致
内容的提问来源于stack exchange,提问作者Liza
相关产品推荐
相关产品推荐

