这是我简单的User
POCO类:
/// <summary>
/// The User class represents a Coderwall User.
/// </summary>
public class User
{
/// <summary>
/// A User's username. eg: "sergiotapia, mrkibbles, matumbo"
/// </summary>
public string Username { get; set; }
/// <summary>
/// A User's name. eg: "Sergio Tapia, John Cosack, Lucy McMillan"
/// </summary>
public string Name { get; set; }
/// <summary>
/// A User's location. eh: "Bolivia, USA, France, Italy"
/// </summary>
public string Location { get; set; }
public int Endorsements { get; set; } //Todo.
public string Team { get; set; } //Todo.
/// <summary>
/// A collection of the User's linked accounts.
/// </summary>
public List<Account> Accounts { get; set; }
/// <summary>
/// A collection of the User's awarded badges.
/// </summary>
public List<Badge> Badges { get; set; }
}
以及我用来将 JSON 响应反序列化为 User
对象的方法(这个实际的 JSON 调用在这里):
private User LoadUserFromJson(string response)
{
var outObject = JsonConvert.DeserializeObject<User>(response);
return outObject;
}
这将触发异常:
无法反序列化当前 JSON 对象(例如 {"名称":"值"}) 成类型 'System.Collections.Generic.List'1[CoderwallDotNet.Api.Models.Account]' 因为该类型需要一个 JSON 数组(例如 [1,2,3])来反序列化 正确。
若要修复此错误,请将 JSON 更改为 JSON 数组 (例如 [1,2,3]) 或更改反序列化类型,使其为正常类型 .NET 类型(例如,不是像整数这样的基元类型,不是集合 类型,类似于数组或列表),可以从 JSON 反序列化 对象。JsonObjectAttribute 也可以添加到类型中以强制它 从 JSON 对象反序列化。路径 'accounts.github', 第 1 行, 位置 129。
以前从未使用过这个反序列化对象方法,我有点卡在这里。
我已确保 POCO 类中的属性名称与 JSON 响应中的名称相同。
我可以尝试将 JSON 反序列化为此 POCO 类吗?
这是一个工作示例。
关键点是:
Accounts
声明JsonProperty
属性的使用
.
using (WebClient wc = new WebClient())
{
var json = wc.DownloadString("http://coderwall.com/mdeiters.json");
var user = JsonConvert.DeserializeObject<User>(json);
}
-
public class User
{
/// <summary>
/// A User's username. eg: "sergiotapia, mrkibbles, matumbo"
/// </summary>
[JsonProperty("username")]
public string Username { get; set; }
/// <summary>
/// A User's name. eg: "Sergio Tapia, John Cosack, Lucy McMillan"
/// </summary>
[JsonProperty("name")]
public string Name { get; set; }
/// <summary>
/// A User's location. eh: "Bolivia, USA, France, Italy"
/// </summary>
[JsonProperty("location")]
public string Location { get; set; }
[JsonProperty("endorsements")]
public int Endorsements { get; set; } //Todo.
[JsonProperty("team")]
public string Team { get; set; } //Todo.
/// <summary>
/// A collection of the User's linked accounts.
/// </summary>
[JsonProperty("accounts")]
public Account Accounts { get; set; }
/// <summary>
/// A collection of the User's awarded badges.
/// </summary>
[JsonProperty("badges")]
public List<Badge> Badges { get; set; }
}
public class Account
{
public string github;
}
public class Badge
{
[JsonProperty("name")]
public string Name;
[JsonProperty("description")]
public string Description;
[JsonProperty("created")]
public string Created;
[JsonProperty("badge")]
public string BadgeUrl;
}
将驼峰大小写的 JSON 字符串反序列化为帕斯卡大小写 POCO 对象的另一种更简化的方法是使用 CamelCasePropertyNamesContractResolver。
它是Newtonsoft.Json.Serialization命名空间的一部分。此方法假定 JSON 对象和 POCO 之间的唯一区别在于属性名称的大小写。如果属性名称的拼写不同,则需要使用 JsonProperty 属性来映射属性名称。
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
. . .
private User LoadUserFromJson(string response)
{
JsonSerializerSettings serSettings = new JsonSerializerSettings();
serSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
User outObject = JsonConvert.DeserializeObject<User>(jsonValue, serSettings);
return outObject;
}
帐户属性定义如下:
"accounts":{"github":"sergiotapia"}
您的 POCO 声明如下:
public List<Account> Accounts { get; set; }
尝试使用此 Json:
"accounts":[{"github":"sergiotapia"}]
项目数组(将映射到列表)始终括在方括号中。
编辑:帐户Poco将是这样的:
class Account {
public string github { get; set; }
}
也许还有其他属性。
编辑 2:要没有数组,请使用如下属性:
public Account Accounts { get; set; }
类似于我在第一次编辑中发布的示例类。
您可以创建一个JsonConverter
。 有关与您的问题类似的示例,请参阅此处。
按照接受的答案,如果你有一个 JSON 文本示例,则可以将其插入到此转换器,选择你的选项并生成 C# 代码。
如果在运行时不知道类型,本主题看起来很合适。
将 JSON 动态反序列化为传入的任何对象。 C#
to fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the
deserialized type so that it is a normal .NET type (e.g. not a primitive type like
integer, not a collection type like an array or List) that can be deserialized from a
JSON object.`
整个消息指示可以序列化为 List 对象,但输入必须是 JSON 列表。这意味着您的 JSON 必须包含
"accounts" : [{<AccountObjectData}, {<AccountObjectData>}...],
其中帐户对象数据是表示帐户对象或徽章对象的 JSON
它目前似乎正在得到的是
"accounts":{"github":"sergiotapia"}
其中帐户是 JSON 对象(用大括号表示),而不是 JSON 对象数组(数组用括号表示),这是您想要的。尝试
"accounts" : [{"github":"sergiotapia"}]
这不完全是我的想法。 如果泛型类型仅在运行时已知,该怎么办?
public MyDTO toObject() {
try {
var methodInfo = MethodBase.GetCurrentMethod();
if (methodInfo.DeclaringType != null) {
var fullName = methodInfo.DeclaringType.FullName + "." + this.dtoName;
Type type = Type.GetType(fullName);
if (type != null) {
var obj = JsonConvert.DeserializeObject(payload);
//var obj = JsonConvert.DeserializeObject<type.MemberType.GetType()>(payload); // <--- type ?????
...
}
}
// Example for java.. Convert this to C#
return JSONUtil.fromJSON(payload, Class.forName(dtoName, false, getClass().getClassLoader()));
} catch (Exception ex) {
throw new ReflectInsightException(MethodBase.GetCurrentMethod().Name, ex);
}
}
可能会迟到,但使用QuickType是最简单的方法:
https://app.quicktype.io/
对于遇到此问题的任何人,我没有正确看到 json 值。 https://jsonutils.com/在那里,您可以检查应该生成的类,并在读取代码中的 json 后仅返回其中一个类。
例如,我需要一个书单对象,所以我的代码应该只读取一个
res = await response.Content.ReadAsAsync<BookList>();
书单看起来像什么
public class BookList
{
[JsonProperty("data")]
public IList<Datum> Data { get; set; }
}
在该列表中,有较小的书包,转换器名为基准(只是书籍)
public class Datum
{
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("isbn")]
public string Isbn { get; set; }
}
同样,如果您有疑问 https://jsonutils.com/