72

这是我的简单UserPOCO 类:

/// <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 对象(例如 {"name":"value"})反序列化为类型“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。

以前从未使用过这种 DeserializeObject 方法,我有点卡在这里。

我已确保 POCO 类中的属性名称与 JSON 响应中的名称相同。

我可以尝试将 JSON 反序列化到这个 POCO 类中吗?

4

9 回答 9

121

这是一个工作示例。

要点是:

  • 宣言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;
}
于 2012-06-20T20:12:34.173 回答
9

将骆驼大小写的 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; 
}
于 2014-12-19T22:05:46.937 回答
6

你可以创建一个JsonConverter. 请参阅此处以获取与您的问题类似的示例。

于 2012-06-20T19:07:29.657 回答
5

帐户属性定义如下:

"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; }

与我在第一次编辑中发布的示例类类似。

于 2012-06-20T18:59:41.810 回答
4

根据接受的答案,如果您有 JSON 文本示例,您可以将其插入此转换器,选择您的选项并生成 C# 代码。

如果您在运行时不知道类型,那么这个主题看起来很合适。

将json动态反序列化为传入的任何对象。c#

于 2017-02-27T23:24:32.633 回答
3
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>}...],

其中 AccountObject 数据是 JSON,表示您的 Account 对象或 Badge 对象

它目前似乎得到的是

"accounts":{"github":"sergiotapia"}

其中 accounts 是 JSON 对象(用大括号表示),而不是 JSON 对象数组(数组用方括号表示),这正是您想要的。尝试

"accounts" : [{"github":"sergiotapia"}]
于 2012-06-20T19:02:35.283 回答
0

这不完全是我的想法。如果你有一个只能在运行时知道的泛型类型,你会怎么做?

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);
  }
}
于 2015-02-26T18:30:48.097 回答
0

对于遇到此问题的任何人,我都没有正确看到 json 值。https://jsonutils.com/在那里,您可以检查应该生成的类,并在您阅读代码中的 json 后仅返回其中一个类。

例如,我需要一个 booklist 对象,所以我的代码应该只读取一个

res = await response.Content.ReadAsAsync<BookList>();

书单看起来像

    public class BookList
    {

        [JsonProperty("data")]
        public IList<Datum> Data { get; set; }
     }

并且在该列表中有较小的书类,即名为 Datum 的转换器(只是书)

    public class Datum
    {

        [JsonProperty("id")]
        public string Id { get; set; }

        [JsonProperty("isbn")]
        public string Isbn { get; set; }
    }

同样,如果您有疑问https://jsonutils.com/

于 2021-11-23T22:31:17.407 回答
0

可能会迟到,但使用 QuickType 是最简单的方法:

https://app.quicktype.io/

于 2021-11-11T22:58:48.783 回答