首页 文章

使用JSON.NET将JSON数据反序列化为C#

提问于
浏览
134

我对使用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"
    ]
}

8 回答

  • 46

    使用 JsonConvert.DeserializeObject<RootObject>(string json);

    JSON 2 C#上创建课程


    Json.NET文档: Serializing and Deserializing JSON with Json.NET

  • 264

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

    JsonConvert.DeserializeObject<MyAccount>(myjsondata);
    

    JSON数据中任何缺少的字段都应该保留为NULL .

    更新:

    如果JSON字符串是数组,请尝试以下操作:

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

    jarray 应该是 List<MyAccount> .

    另一个更新:

    您与对象数组一致的异常 - 我认为序列化程序在使用Dictionary类型 accountstatusmodifiedby 属性时遇到问题 .

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

    文件: Serializing and Deserializing JSON with Json.NET

  • 73

    从https://stackoverflow.com/a/10718128/776476转载的答案

    您可以使用C# dynamic 类型来简化操作 . 这种技术也使得重新分解更简单,因为它不依赖于魔术字符串 .

    Json

    下面的 json 字符串是来自http api调用的简单响应,它定义了两个属性: IdName .

    {"Id": 1, "Name": "biofractal"}
    

    C#

    使用 JsonConvert.DeserializeObject<dynamic>() 将此字符串反序列化为动态类型,然后以通常的方式访问其属性 .

    var results = JsonConvert.DeserializeObject<dynamic>(json);
    var id = results.Id;
    var name= results.Name;
    

    注意:NewtonSoft程序集的NuGet链接是http://nuget.org/packages/newtonsoft.json . 不要忘记添加: using Newtonsoft.Json; 来访问这些类 .

  • 1

    您可以使用:

    JsonConvert.PopulateObject(json, obj);
    

    这里: json 是json字符串, obj 是目标对象 . 见:example

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

  • 1

    基于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 Class Generator生成的类

    这是我使用的设置的屏幕截图,允许web version无法解释的奇怪的属性名称 .

    Xamasoft JSON Class Generator

  • 8

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

    以下代码是在考虑动态方法的情况下完成的 .

    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字符串中包含的成员 . 只是一种不同的方式而不需要课程 . querytrendurl 是Json字符串中包含的对象 .

    您也可以使用this website . 不要相信100%的课程,但你明白了 .

  • 0

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

  • 3

    假设您的示例数据是正确的,您的给定名称和括在括号中的其他条目是JS中的数组...您将希望对这些数据类型使用List . 并列出了例如accountstatusexpmaxdate ...我认为你的例子的日期格式不正确,所以不确定你的例子中还有哪些不正确 .

    这是一篇旧帖子,但想要记下这些问题 .

相关问题