ASP.NET Framework调用API绑定GridView报Newtonsoft.Json序列化错误如何解决
ASP.NET Framework中HttpClient调用API绑定GridView序列化报错解决
问题背景
使用ASP.NET Framework开发时,通过HttpClient调用API接口获取成员列表数据,计划将返回数据绑定到GridView控件,接口返回示例JSON如下:
{ "success": true, "status": 200, "data": [ { "ProfileID": "1001", "Name": "Jane Doe", "HomePhone": "555-1212", "Address1": "123 Elm St" }, { "ProfileID": "1002", "Name": "Rick Fox", "HomePhone": "555-1213", "Address1": "123 Ok St" } ] }
初始代码与报错信息
初始编写的绑定逻辑代码如下:
using Newtonsoft.Json; private void popGrid() { var client = new HttpClient(); client.BaseAddress = new Uri("http://the-api/"); var responseTask = client.GetAsync("member-list"); responseTask.Wait(); var result = responseTask.Result; if (result.IsSuccessStatusCode) { var read_response = responseTask.Result.Content.ReadAsStringAsync(); read_response.Wait(); var read_result = read_response.Result; dynamic response = JsonConvert.DeserializeObject(read_result); var success = response.success; var status = response.status; var data = response.data; // List<Root> myDeserializedClass = JsonConvert.DeserializeObject<List<Root>>(data); if ((bool)success) { GridView1.DataSource = data; GridView1.DataBind(); } } } public class Root { public string ProfileID { get; set; } public string Name { get; set; } public string HomePhone { get; set; } public string Address1 { get; set; } }
代码执行全程无异常,但页面渲染阶段抛出如下错误:
Type 'Newtonsoft.Json.Linq.JValue' in Assembly 'Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' is not marked as serializable.
堆栈跟踪关键报错线索:
[ArgumentException: Error serializing value '1001' of type 'Newtonsoft.Json.Linq.JValue.']
后续尝试取消注释强类型反序列化代码行,又抛出如下参数不匹配错误:
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'The best overloaded method match for 'Newtonsoft.Json.JsonConvert.DeserializeObject<System.Collections.Generic.List<Root>>(string)' has some invalid arguments'
问题根因
- 首次报错:直接绑定dynamic反序列化得到的
JArray对象作为数据源时,数组内对象的属性值都是Newtonsoft.Json.Linq.JValue类型,该类型未标记可序列化特性,GridView在渲染序列化数据源时就会抛出异常。 - 二次报错:
JsonConvert.DeserializeObject<T>()方法要求入参是原始JSON字符串,但代码中传入的data是已经解析完成的JToken对象,类型不匹配导致运行时绑定错误。
最终可运行实现
通过将API返回的data节点直接转换为DataTable作为GridView数据源,不需要额外做类型映射即可适配WebForm控件的序列化要求,调整后的完整代码如下:
using Newtonsoft.Json; using Newtonsoft.Json.Linq; const string theAPI = "http://the-api/"; const string otherAPI = "http://other-api/"; protected void Button2_Click(object sender, EventArgs e) { DataTable dt = GetDataTableFromAPI(theAPI, "member-list"); if (dt.Rows.Count > 0) { GridView1.DataSource = dt; GridView1.DataBind(); GridView1.HeaderRow.TableSection = TableRowSection.TableHeader; } else { // 无匹配数据处理逻辑 } } public DataTable GetDataTableFromAPI(string api, string endPoint) { var client = new HttpClient(); client.BaseAddress = new Uri(api); var response = client.GetAsync(endPoint).Result; if (response.IsSuccessStatusCode) { var json = response.Content.ReadAsStringAsync().Result; var jsonParsed = JObject.Parse(json); var success = jsonParsed["success"]; var status = jsonParsed["status"]; if ((bool)success) { DataTable dt = jsonParsed["data"].ToObject<DataTable>(); return dt; } } return new DataTable(); }
内容的提问来源于stack exchange,提问作者JonV
相关产品推荐
相关产品推荐

