使用 JsonConvert.DeserializeObject 将 Json 反序列化为 C# POCO 类

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11126242/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 16:37:36  来源:igfitidea点击:

Using JsonConvert.DeserializeObject to deserialize Json to a C# POCO class

c#jsonserializationjson.netpoco

提问by Only Bolivian Here

Here is my simple UserPOCO class:

这是我的简单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; }

}

And the method I'm using to deserialize a JSON response into a Userobject (this actual JSON call is here):

我用来将 JSON 响应反序列化为User对象的方法(这个实际的JSON 调用在这里):

private User LoadUserFromJson(string response)
{
    var outObject = JsonConvert.DeserializeObject<User>(response);
    return outObject;
}

This fires an exception:

这会引发异常:

Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[CoderwallDotNet.Api.Models.Account]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.

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. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object. Path 'accounts.github', line 1, position 129.

无法将当前 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。

Having never worked with this DeserializeObject method before, I'm kind of stuck here.

以前从未使用过这个 DeserializeObject 方法,我有点被困在这里。

I've made sure that the property names in the POCO class are the same as the names in the JSON response.

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

What can I try to deserialize JSON into this POCO class?

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

采纳答案by L.B

Here is a working example.

这是一个工作示例。

Keypoints are:

要点是:

  • Declaration of Accounts
  • Use of JsonPropertyattribute
  • 声明 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;
}

回答by Sascha

The accounts property is defined like this:

account 属性定义如下:

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

Your POCO states this:

您的 POCO 声明如下:

public List<Account> Accounts { get; set; }

Try using this Json:

尝试使用这个 Json:

"accounts":[{"github":"sergiotapia"}]

An array of items (which is going to be mapped to the list) is always enclosed in square brackets.

项目数组(将被映射到列表)总是用方括号括起来。

Edit:The Account Poco will be something like this:

编辑:帐户 Poco 将是这样的:

class Account {
    public string github { get; set; }
}

and maybe other properties.

也许还有其他属性。

Edit 2:To not have an array use the property as follows:

编辑 2:要没有数组,请按如下方式使用该属性:

public Account Accounts { get; set; }

with something like the sample class I've posted in the first edit.

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

回答by dmi_

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.`

The whole message indicates that it is possible to serialize to a List object, but the input must be a JSON list. This means that your JSON must contain

整个消息表明可以序列化为 List 对象,但输入必须是 JSON 列表。这意味着您的 JSON 必须包含

"accounts" : [{<AccountObjectData}, {<AccountObjectData>}...],

Where AccountObject data is JSON representing your Account object or your Badge object

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

What it seems to be getting currently is

目前似乎得到的是

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

Where accounts is a JSON object (denoted by curly braces), not an array of JSON objects (arrays are denoted by brackets), which is what you want. Try

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

"accounts" : [{"github":"sergiotapia"}]

回答by SwDevMan81

You could create a JsonConverter. See herefor an example thats similar to your question.

您可以创建一个JsonConverter. 有关与您的问题类似的示例,请参见此处

回答by John Iwasz

Another, and more streamlined, approach to deserializing a camel-cased JSON string to a pascal-cased POCO object is to use the CamelCasePropertyNamesContractResolver.

另一种更简化的将驼峰式 JSON 字符串反序列化为 pascal 式 POCO 对象的方法是使用CamelCasePropertyNamesContractResolver

It's part of the Newtonsoft.Json.Serialization namespace. This approach assumes that the only difference between the JSON object and the POCO lies in the casing of the property names. If the property names are spelled differently, then you'll need to resort to using JsonProperty attributes to map property names.

它是 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; 
}

回答by Latency

That's not exactly what I had in mind. What do you do if you have a generic type to only be known at runtime?

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

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

回答by Jim

Along the lines of the accepted answer, if you have a JSON text sample you can plug it in to this converter, select your options and generate the C# code.

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

If you don't know the type at runtime, this topic looks like it would fit.

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

dynamically deserialize json into any object passed in. c#

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