C#中LINQ语句报Unable to cast object of type转换异常如何解决
问题描述
执行到代码行var columnNames =时抛出以下类型转换异常:
System.InvalidCastException: 'Unable to cast object of type 'System.Object' to type 'System.Collections.Generic.Dictionary`2[System.String,System.Object]'.'
对应后端业务代码如下:
public JsonResult SaveData(List<object> customers) { DataTable dt = new DataTable(); var columnNames = ((Dictionary<string, object>)customers[0]).Select(x => x.Key).ToList(); for (int i = 0; i < columnNames.Count(); i++) { dt.Columns.Add(columnNames[i]); } foreach (Dictionary<string, object> customer in customers) { DataRow dr = dt.NewRow(); for (int i = 0; i < columnNames.Count(); i++) { dr[columnNames[i]] = customer[columnNames[i]]; } dt.Rows.Add(dr); } return Json('1'); }
前端传递的参数在浏览器控制台打印格式如下:
0 : {Id: "1", Name: "abc", Country: "uk", __rowNum__: 1} 1: {Id: "2", Name: "kala", Country: "us", __rowNum__: 2} 2: {Id: "3", Name: "Has", Country: "IN", __rowNum__: 3}
问题根因
把接口参数定义成List<object>后,ASP.NET 的模型绑定器反序列化前端传来的JSON对象时,不会自动把集合里的每个JSON对象转成Dictionary<string,object>:根据项目用的序列化组件不同,集合元素实际运行时类型是System.Text.Json.JsonElement(.NET Core/5+ 默认序列化配置)或者Newtonsoft.Json.Linq.JObject(.NET Framework 或手动切换序列化组件为Newtonsoft.Json的场景),直接硬转Dictionary必然抛出类型转换异常。
排查&解决方法
- 第一步先确认实际类型:在报错行前打断点,调试时查看
customers[0].GetType().FullName,就能拿到元素的真实运行时类型,避免盲目强转。 - 最优方案:直接修改接口参数类型为
List<Dictionary<string, object>>,让模型绑定器自动完成反序列化,无需手动强转。修改后的可运行代码如下:
public JsonResult SaveData(List<Dictionary<string, object>> customers) { DataTable dt = new DataTable(); // 无需强转,直接取Key作为DataTable列名 var columnNames = customers[0].Select(x => x.Key).ToList(); for (int i = 0; i < columnNames.Count; i++) { dt.Columns.Add(columnNames[i]); } foreach (var customer in customers) { DataRow dr = dt.NewRow(); for (int i = 0; i < columnNames.Count; i++) { dr[columnNames[i]] = customer[columnNames[i]]; } dt.Rows.Add(dr); } // 注意C#中字符串用双引号包裹,单引号代表char类型,原写法会触发编译错误 return Json("1"); }
- 兼容方案:如果因为业务逻辑限制不能修改参数类型,就根据项目实际使用的序列化组件做对应转换:
- 使用System.Text.Json的场景:
var firstCustomer = JsonSerializer.Deserialize<Dictionary<string, object>>(customers[0]!.ToString()!); var columnNames = firstCustomer.Select(x => x.Key).ToList(); // 遍历集合时,每个元素都调用JsonSerializer反序列化为Dictionary<string,object>再处理即可 - 使用Newtonsoft.Json的场景:
var firstCustomer = (customers[0] as JObject)?.ToObject<Dictionary<string, object>>(); var columnNames = firstCustomer.Select(x => x.Key).ToList(); // 遍历集合时,每个JObject元素调用ToObject<Dictionary<string,object>>()转换后再处理即可
- 使用System.Text.Json的场景:
内容的提问来源于stack exchange,提问作者atc
相关产品推荐
相关产品推荐

