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

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

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

我一直在做什么似乎是错误的,很难的方式,只是从JObject中逐个挑选每个值,并将string转换为所需的类属性。

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

而要parsing的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" ] } 

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

在JSON 2上创build你的类C#


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

你有没有尝试过使用通用的DeserializeObject方法?

 JsonConvert.DeserializeObject<MyAccount>(myjsondata); 

JSON数据中任何缺less的字段都应该保留NULL。

更新:

如果JSONstring是一个数组,请尝试以下操作:

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

然后jarray应该是一个List<MyAccount> jarray List<MyAccount>

其他更新:

你得到的exception是与一个对象数组不一致 – 我认为序列化程序与你的字典typesaccountstatusmodifiedby属性有问题。

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

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

回答从https://stackoverflow.com/a/10718128/776476转载;

您可以使用C# dynamictypes来使事情更轻松。 这种技术也使重build更简单,因为它不依赖于魔术string。

JSON

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

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

C#

使用JsonConvert.DeserializeObject<dynamic>()将该string反序列化为一个dynamictypes,然后以通常的方式访问它的属性。

 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; 访问这些类。

您可以使用:

 JsonConvert.PopulateObject(json, obj); 

这里: json是jsonstring, obj是目标对象。 见: 例子

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

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

 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类生成器

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

下面的代码是考虑到dynamic的方法。

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

这段代码基本上允许你访问包含在Jsonstring中的成员。 只是一种不需要课程的不同方式。 querytrendurl是包含在Jsonstring中的对象。

你也可以使用这个网站 。 不要相信100%的课,但你明白了。

我发现我不正确地build立了我的对象。 我用http://json2csharp.com/从JSON生成我的对象类。; 一旦我有了正确的Oject,我就能毫无问题地施放。 Norbit,Noob错误。 以为我会添加它,如果你有同样的问题。

假设您的示例数据是正确的,您的给定名称和其他条目包装在方括号是JS中的数组…您将要使用列表这些数据types。 和列表为说accountstatusexpmaxdate …我认为你的例子有错误地格式化的date,所以不确定,在你的例子中还有什么是不正确的。

这是一个旧post,但要记下这个问题。