[英]Unable to read json comes from Web API in C#
无法将 webapi 值读取到列表对象。 请查看链接http://prntscr.com/lcmw7q 中的屏幕截图值。
错误是Newtonsoft.Json.JsonSerializationException: 'Cannot deserialize the current JSON object (eg {"name":"value"}) 到 type 'System.Collections.Generic.List`1[StudentProfileClient.StudentInfo]' 因为该类型需要一个JSON 数组(例如 [1,2,3])以正确反序列化。 要修复此错误,请将 JSON 更改为 JSON 数组(例如 [1,2,3])或更改反序列化类型,使其成为正常的 .NET 类型(例如,不是像整数这样的原始类型,而不是像这样的集合类型)可以从 JSON 对象反序列化的数组或列表)。 JsonObjectAttribute 也可以添加到类型中以强制它从 JSON 对象反序列化。 路径“数据”,第 2 行,位置 10。
class StudentInfo
{
public string cellPhone { get; set; }
public string gender { get; set; }
public string dateOfBirth { get; set; }
}
class RootClass
{
public int TotalCount { get; set; }
public List<StudentInfo> stdinfo { get; set; }
}
static async Task GetData()
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://203.81.70.102:8092/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response;
response = await client.GetAsync("control/qZkNkcGgWq6PiVbJzQ2=/student-profiles");
if (response.IsSuccessStatusCode)
{
List<StudentInfo> RootClass = new List<StudentInfo>();
RootClass = await response.Content.ReadAsAsync<List<StudentInfo>>();
}
}
}
您不能使用 JsonConvert.DeserializeObject 从 API 响应中直接反序列化。 ——
JObject jsonResponse = JObject.Parse(jsonString);
JObject objResponse = (JObject)jsonResponse["response"];
Dictionary<string, JArray> _Data = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, JArray>>(objResponse.ToString());
不要将 RootClass 声明为 List,而是使用:
var RootClass = 等待 response.Content.ReadAsAsync()
在行中放置一个断点,并检查从 API 返回的类型。 由于 var 将接受任何内容,您可以检查响应。 基本上,您的错误表明您正在尝试将 CAST 转换为无效类型,因此反序列化无法正常工作。
似乎返回的对象是一个数组,也许您需要获取该数组并将其转换为列表,或者甚至是与您期望的对象完全不同的对象,具有其他属性等...
解决的最佳方法 ->调试,并确保您使用正确的类型进行反序列化
1) 通过在Newtonsoft.json
使用JObject
。
在包管理器控制台中键入以下命令。
Install-Package Newtonsoft.Json
if (response.IsSuccessStatusCode)
{
string json = await response.Content.ReadAsStringAsync();
JObject jObject = JObject.Parse(json);
List<StudentInfo> studentInfos = jObject["data"].ToObject<List<StudentInfo>>();
}
输出:
2) 不使用Newtonsoft.json
。
在包管理器控制台中键入以下命令。
Install-Package Microsoft.AspNet.WebApi.Client
if (response.IsSuccessStatusCode)
{
RootClass rootClass = await response.Content.ReadAsAsync<RootClass>();
List<StudentInfo> studentInfos = rootClass.data;
}
输出:
所以你的课程将是
public class StudentInfo
{
public int sl { get; set; }
public string studentId { get; set; }
public string studentName { get; set; }
public string school { get; set; }
public string program { get; set; }
public string fatherName { get; set; }
public string motherName { get; set; }
public string cellPhone { get; set; }
public string gender { get; set; }
public string dateOfBirth { get; set; }
}
public class RootClass
{
public List<StudentInfo> data { get; set; }
public string message { get; set; }
public int total { get; set; }
}
简单的解决方案,你需要一个包装器
这在实践中是什么样子的? 它只是意味着返回对象列表的 API 将列表包装在顶级对象中。 例如,假设您的 API 中有一个 Person 数据类型。 如果您 GET 一个 Person,您最终可能会得到以下 JSON 响应:
{ "name": "John Smith" }
到目前为止一切都很好。 但是如果你想要一个列表而不是一个列表呢? 最直观的方式可能如下:
[{"name": "John Smith"}, {"name": "Jane Smith"}]
但这正是我们需要避免的情况。 因此,我们需要为这样的列表使用顶级对象,并具有单个数据属性:
{"data": [{"name": "John Smith"}, {"name": "Jane Smith"}]}
所以.....
Class Students{
public List<StudentInfo> roots{get;set;}
}
保留你的学生班级,添加我班级的学生,然后反序列化;
所以你有一个叫做 RootClass 的类。 您有一个名为 StudentInfo 的类。
你希望得到哪一个? 似乎你得到了完全不同的东西。 正如我在这里看到的, https: //prnt.sc/lcnlho ,您应该创建一个新类(或更改 RootClass 结构),如下所示
class ResponseContainer
{
public List<StudentInfo> data { get; set; }
}
而不是直接反序列化到 List,你应该反序列化到这个 ResponseContainer 类:
var response = await response.Content.ReadAsAsync<ResponseContainer>();
ps 如果你想使用你的 RootClass,你应该将属性 stdinfo 重命名为“data”,或者像这样添加 JsonProperty 属性:
class RootClass
{
public int TotalCount { get; set; }
[JsonProperty(PropertyName = "data")]
public List<StudentInfo> stdinfo { get; set; }
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.