使用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
您可以使用C# dynamic
types来使事情更轻松。 这种技术也使重build更简单,因为它不依赖于魔术string。
JSON
下面的json
string是来自http api调用的简单响应,它定义了两个属性: Id
和Name
。
{"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版本无法解释的奇怪的属性名称。
您可以尝试在线查看一些类生成器以获取更多信息。 但是,我相信一些答案是有用的。 这是我的方法,可能是有用的。
下面的代码是考虑到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中的成员。 只是一种不需要课程的不同方式。 query
, trend
和url
是包含在Jsonstring中的对象。
你也可以使用这个网站 。 不要相信100%的课,但你明白了。
我发现我不正确地build立了我的对象。 我用http://json2csharp.com/从JSON生成我的对象类。; 一旦我有了正确的Oject,我就能毫无问题地施放。 Norbit,Noob错误。 以为我会添加它,如果你有同样的问题。
假设您的示例数据是正确的,您的给定名称和其他条目包装在方括号是JS中的数组…您将要使用列表这些数据types。 和列表为说accountstatusexpmaxdate …我认为你的例子有错误地格式化的date,所以不确定,在你的例子中还有什么是不正确的。
这是一个旧post,但要记下这个问题。