146

我对使用 C# 和 JSON 数据比较陌生,正在寻求指导。我正在使用 C# 3.0、.NET3.5SP1 和 JSON.NET 3.5r6。

我有一个已定义的 C# 类,我需要从 JSON 结构中填充它。但是,并非从 Web 服务检索到的条目的每个 JSON 结构都包含在 C# 类中定义的所有可能属性。

我一直在做似乎是错误的、艰难的方法,只是从 JObject 中一一挑选出每个值并将字符串转换为所需的类属性。

JsonSerializer serializer = new JsonSerializer();
var o = (JObject)serializer.Deserialize(myjsondata);

MyAccount.EmployeeID = (string)o["employeeid"][0];

将 JSON 结构反序列化为 C# 类并处理 JSON 源中可能丢失的数据的最佳方法是什么?

我的班级定义为:

  public class MyAccount
  {

    [JsonProperty(PropertyName = "username")]
    public string UserID { get; set; }

    [JsonProperty(PropertyName = "givenname")]
    public string GivenName { get; set; }

    [JsonProperty(PropertyName = "sn")]
    public string Surname { get; set; }

    [JsonProperty(PropertyName = "passwordexpired")]
    public DateTime PasswordExpire { get; set; }

    [JsonProperty(PropertyName = "primaryaffiliation")]
    public string PrimaryAffiliation { get; set; }

    [JsonProperty(PropertyName = "affiliation")]
    public string[] Affiliation { get; set; }

    [JsonProperty(PropertyName = "affiliationstatus")]
    public string AffiliationStatus { get; set; }

    [JsonProperty(PropertyName = "affiliationmodifytimestamp")]
    public DateTime AffiliationLastModified { get; set; }

    [JsonProperty(PropertyName = "employeeid")]
    public string EmployeeID { get; set; }

    [JsonProperty(PropertyName = "accountstatus")]
    public string AccountStatus { get; set; }

    [JsonProperty(PropertyName = "accountstatusexpiration")]
    public DateTime AccountStatusExpiration { get; set; }

    [JsonProperty(PropertyName = "accountstatusexpmaxdate")]
    public DateTime AccountStatusExpirationMaxDate { get; set; }

    [JsonProperty(PropertyName = "accountstatusmodifytimestamp")]
    public DateTime AccountStatusModified { get; set; }

    [JsonProperty(PropertyName = "accountstatusexpnotice")]
    public string AccountStatusExpNotice { get; set; }

    [JsonProperty(PropertyName = "accountstatusmodifiedby")]
    public Dictionary<DateTime, string> AccountStatusModifiedBy { get; set; }

    [JsonProperty(PropertyName = "entrycreatedate")]
    public DateTime EntryCreatedate { get; set; }

    [JsonProperty(PropertyName = "entrydeactivationdate")]
    public DateTime EntryDeactivationDate { get; set; }

  }

要解析的 JSON 样本是:

{
    "givenname": [
        "Robert"
    ],
    "passwordexpired": "20091031041550Z",
    "accountstatus": [
        "active"
    ],
    "accountstatusexpiration": [
        "20100612000000Z"
    ],
    "accountstatusexpmaxdate": [
        "20110410000000Z"
    ],
    "accountstatusmodifiedby": {
        "20100214173242Z": "tdecker",
        "20100304003242Z": "jsmith",
        "20100324103242Z": "jsmith",
        "20100325000005Z": "rjones",
        "20100326210634Z": "jsmith",
        "20100326211130Z": "jsmith"
    },
    "accountstatusmodifytimestamp": [
        "20100312001213Z"
    ],
    "affiliation": [
        "Employee",
        "Contractor",
        "Staff"
    ],
    "affiliationmodifytimestamp": [
        "20100312001213Z"
    ],
    "affiliationstatus": [
        "detached"
    ],
    "entrycreatedate": [
        "20000922072747Z"
    ],
    "username": [
        "rjohnson"
    ],
    "primaryaffiliation": [
        "Staff"
    ],
    "employeeid": [
        "999777666"
    ],
    "sn": [
        "Johnson"
    ]
}
4

7 回答 7

285

利用

var rootObject =  JsonConvert.DeserializeObject<RootObject>(string json);

在JSON 2 C#上创建你的类


Json.NET 文档:使用 Json.NET 序列化和反序列化 JSON

于 2012-01-27T18:36:35.043 回答
79

您是否尝试过使用通用的 DeserializeObject 方法?

JsonConvert.DeserializeObject<MyAccount>(myjsondata);

JSON 数据中任何缺失的字段都应该简单地保留为 NULL。

更新:

如果 JSON 字符串是一个数组,试试这个:

var jarray = JsonConvert.DeserializeObject<List<MyAccount>>(myjsondata);

jarray那么应该是一个List<MyAccount>.

另一个更新:

您得到的异常与对象数组不一致 - 我认为序列化程序与您的 Dictionary-typedaccountstatusmodifiedby属性有问题。

尝试accountstatusmodifiedby 从序列化中排除该属性,看看是否有帮助。如果是这样,您可能需要以不同的方式表示该属性。

文档:使用 Json.NET 序列化和反序列化 JSON

于 2010-03-30T15:03:26.097 回答
8

您可以使用:

JsonConvert.PopulateObject(json, obj);

这里:json是json字符串,obj是目标对象。请参阅:示例

注意:PopulateObject()不会擦除obj的列表数据,之后Populate()obj's列表成员将包含其原始数据和json字符串中的数据

于 2011-12-22T16:25:29.863 回答
3

基于 bbant 的回答,这是我从远程 URL 反序列化 JSON 的完整解决方案。

using Newtonsoft.Json;
using System.Net.Http;

namespace Base
{
    public class ApiConsumer<T>
    {
        public T data;
        private string url;

        public CalendarApiConsumer(string url)
        {
            this.url = url;
            this.data = getItems();
        }

        private T getItems()
        {
            T result = default(T);
            HttpClient client = new HttpClient();

            // This allows for debugging possible JSON issues
            var settings = new JsonSerializerSettings
            {
                Error = (sender, args) =>
                {
                    if (System.Diagnostics.Debugger.IsAttached)
                    {
                        System.Diagnostics.Debugger.Break();
                    }
                }
            };

            using (HttpResponseMessage response = client.GetAsync(this.url).Result)
            {
                if (response.IsSuccessStatusCode)
                {
                    result = JsonConvert.DeserializeObject<T>(response.Content.ReadAsStringAsync().Result, settings);
                }
            }
            return result;
        }
    }
}

用法如下:

ApiConsumer<FeedResult> feed = new ApiConsumer<FeedResult>("http://example.info/feeds/feeds.aspx?alt=json-in-script");

FeedResult使用Xamasoft JSON 类生成器生成的类在哪里

这是我使用的设置的屏幕截图,允许使用Web 版本无法解释的奇怪属性名称。

Xamasoft JSON 类生成器

于 2014-07-31T15:58:01.810 回答
2

我发现我错误地构建了我的对象。我使用http://json2csharp.com/从 JSON 生成我的对象类。一旦我有了正确的对象,我就可以毫无问题地进行投射。诺比特,菜鸟的错误。以为我会添加它以防您遇到同样的问题。

于 2015-08-20T10:39:48.467 回答
1

您可以尝试在线检查一些类生成器以获取更多信息。但是,我相信一些答案是有用的。这是我可能有用的方法。

以下代码是在考虑动态方法的情况下编写的。

dynObj = (JArray) JsonConvert.DeserializeObject(nvm);

foreach(JObject item in dynObj) {
 foreach(JObject trend in item["trends"]) {
  Console.WriteLine("{0}-{1}-{2}", trend["query"], trend["name"], trend["url"]);
 }
}

此代码基本上允许您访问包含在 Json 字符串中的成员。只是一种不同的方式,不需要上课。query,是 Json 字符串中包含的对象trendurl

您也可以使用本网站。不要 100% 相信课程,但你明白了。

于 2012-09-04T14:42:27.763 回答
-1

假设您的示例数据是正确的,您的给定名称和括在括号中的其他条目是 JS 中的数组......您将希望将 List 用于这些数据类型。并列出 accountstatusexpmaxdate ... 我认为您的示例的日期格式不正确,因此不确定您的示例中还有哪些不正确的地方。

这是一个旧帖子,但想记录下这些问题。

于 2012-04-12T19:26:09.447 回答