C#使用Json.NET解析Json
本文轉(zhuǎn)載自?http://xiaosheng.me/2016/10/01/article25/
最近在 C# 項(xiàng)目中需要使用到 Json 格式的數(shù)據(jù),我簡(jiǎn)單上網(wǎng)搜索了一下,基本上有兩種操作 Json 數(shù)據(jù)的方法:
- 使用 Windows 系統(tǒng)自帶的類(lèi)
- 使用第三方的包
本著“第三方包一定有比系統(tǒng)自帶類(lèi)優(yōu)秀地方,否則就不會(huì)存在”的原則,再加上?JavaScriptSerializer、DataContractJsonSerializer?等這些自帶類(lèi)庫(kù)使用起來(lái)很麻煩,我毫不猶豫地就選擇了在 Json 操作方面小有名氣的?Json.NET。Json.NET 自己也做了與自帶類(lèi)庫(kù)的比較,詳情可以見(jiàn)?Json.NET vs .NET Serializers?和?Json.NET vs Windows.Data.Json。
Json.NET 是一個(gè) Newtonsoft 編寫(xiě)的開(kāi)源類(lèi)庫(kù)包,你可以直接到 Github 上查看項(xiàng)目的源碼和說(shuō)明。Json.NET 提供了大量對(duì)于 Json 數(shù)據(jù)的操作方法,他們使用起來(lái)非常簡(jiǎn)單,而且執(zhí)行效率很高。
.NET 對(duì)象的序列化和反序列化
1. 普通對(duì)象的序列化和反序列化
JsonConvert?是 Json.NET 中的一個(gè)數(shù)據(jù)轉(zhuǎn)換類(lèi),提供了用于 .NET 對(duì)象序列化和反序列化的方法?SerializeObject()?和?DeserializeObject()。在通常情況下,我們也只需要使用這兩個(gè)方法就足以完成任務(wù)了。
比如說(shuō),我們現(xiàn)在定義了一個(gè)學(xué)生類(lèi) Student:
class Student //學(xué)生類(lèi) {public int Id { get; set;} //學(xué)號(hào)public string Name { get; set;} //姓名public double[] Scores { get; set;} //成績(jī) }現(xiàn)在我們創(chuàng)建一個(gè)學(xué)生類(lèi)對(duì)象,并使用?JsonConvert?類(lèi)提供的?SerializeObject()?方法將它轉(zhuǎn)換到 Json 字符串(需要引入命名空間 using Newtonsoft.Json):
Student student = new Student {Id = 12883,Name = "Jim David",Scores = new double[] { 87.5, 92, 76.2 } };string jsonStudent = JsonConvert.SerializeObject(student); //{"Id":12883,"Name":"Jim David","Scores":[87.5,92.0,76.2]}可以看到在序列化的過(guò)程中,JsonConvert?會(huì)將 .NET 對(duì)象中的變量名轉(zhuǎn)換為 Json 中的“屬性”,同時(shí)將變量的值復(fù)制為 Json 的“屬性值”。接下來(lái),我們嘗試將 Json 字符串轉(zhuǎn)換為?Student?對(duì)象,使用?JsonConvert?提供的?DeserializeObject()?方法:
Student deserializedStudent = JsonConvert.DeserializeObject<Student>(jsonStudent); Console.WriteLine("student.Id = " + deserializedStudent.Id); //student.Id = 12883 Console.WriteLine("student.Name = " + deserializedStudent.Name); //student.Name = Jim David可以看到,創(chuàng)建的學(xué)生對(duì)象?student?的 Json 字符串被順利地解析成了 Student 對(duì)象。在調(diào)用?DeserializeObject()?方法進(jìn)行反序列化時(shí),最好使用帶泛型參數(shù)的重載方法。
如果在調(diào)用 DeserializeObject() 時(shí)不指定對(duì)象類(lèi)型,JsonConvert 會(huì)默認(rèn)轉(zhuǎn)換為 Object 對(duì)象。集合的序列化和反序列化
上面我們已經(jīng)簡(jiǎn)單測(cè)試了 JsonConvert 提供的?SerializeObject()?和?DeserializeObject()?方法,完成了 .NET 對(duì)象的序列化和反序列化。
C# 項(xiàng)目中,除了自定義的類(lèi)型外,集合(Collections)也是經(jīng)常會(huì)使用的數(shù)據(jù)類(lèi)型,包括列表、數(shù)組、字典或者我們自定義的集合類(lèi)型。我們同樣可以使用之前使用的?SerializeObject()?和?DeserializeObject()?方法來(lái)完成集合的序列化和反序列化。
為了使轉(zhuǎn)換后的結(jié)果更加易讀,我指定轉(zhuǎn)換后的 Json 字符串帶縮進(jìn)。通過(guò)向 SerializeObject() 方法傳遞進(jìn)第二個(gè)參數(shù) Formatting 實(shí)現(xiàn)。 Student student1 = new Student {Id = 12883,Name = "Jim David",Scores = new double[] { 87.5, 92, 76.2 } }; Student student2 = new Student {Id = 35228,Name = "Milly Smith",Scores = new double[] { 92.5, 88, 85.7 } }; List<Student> students = new List<Student>(); students.Add(student1); students.Add(student2); string jsonStudents = JsonConvert.SerializeObject(students, Formatting.Indented); //[ // { // "Id": 12883, // "Name": "Jim David", // "Scores": [ // 87.5, // 92.0, // 76.2 // ] // }, // { // "Id": 35228, // "Name": "Milly Smith", // "Scores": [ // 92.5, // 88.0, // 85.7 // ] // } //]接下來(lái)我們對(duì)上面生成的 Json 字符串進(jìn)行反序列化,解析出原有的 Student 類(lèi)型列表。同樣,我們需要使用帶泛型參數(shù)的?DeserializeObject()?方法,指定 JsonConvert 解析的目標(biāo)類(lèi)型。
string jsonStudentList = @"[{'Id': 12883,'Name': 'Jim David','Scores': [87.5,92.0,76.2]},{'Id': 35228,'Name': 'Milly Smith','Scores': [92.5,88.0,85.7]} ]";List<Student> studentsList = JsonConvert.DeserializeObject<List<Student>>(jsonStudentList); Console.WriteLine(studentsList.Count); //2 Student s = studentsList[0]; Console.WriteLine(s.Name); //Jim David如果 Json 對(duì)象擁有統(tǒng)一類(lèi)型的屬性和屬性值,我們還可以把 Json 字符串反序列化為 .NET 中的字典,Json 對(duì)象的“屬性”和“屬性值”會(huì)依次賦值給字典中的 Key 和 Value。下面我舉一個(gè)簡(jiǎn)單的例子:
string json = @"{""English"":88.2,""Math"":96.9}"; Dictionary<string, double> values = JsonConvert.DeserializeObject<Dictionary<string, double>>(json); Console.WriteLine(values.Count); //2 Console.WriteLine(values["Math"]); //96.9解析復(fù)雜的 Json 字符串
如今大量的 Web API 為我們編寫(xiě)復(fù)雜程序提供了極大的方便,例如百度地圖 API、圖靈機(jī)器人 API等等,利用這些 Web 應(yīng)用程序我們可以充分發(fā)揮云服務(wù)的優(yōu)勢(shì),開(kāi)發(fā)出大量有趣的應(yīng)用。
Web API 通常返回 Json 或 XML 格式的檢索數(shù)據(jù),由于 Json 數(shù)據(jù)量更小,所以目前大多數(shù)情況下我們都選擇返回 Json 格式的數(shù)據(jù)。
如果返回的 Json 文檔很大,而我們僅僅需要其中的一小部分?jǐn)?shù)據(jù)。按照之前的方法,我們必須首先定義一個(gè)與 Json 對(duì)象對(duì)應(yīng)的 .NET 對(duì)象,然后反序列化,最后才能從對(duì)象中取出我們需要的數(shù)據(jù)。而有了 Json.NET,這個(gè)任務(wù)就很容易實(shí)現(xiàn)了,我們可以局部地解析一個(gè) Json 對(duì)象。
下面以獲取 Google 搜索結(jié)果為例,簡(jiǎn)單演示一下對(duì)復(fù)雜結(jié)構(gòu) Json 文檔的解析。
string googleSearchText = @"{'responseData': {'results': [{'GsearchResultClass': 'GwebSearch','unescapedUrl': 'http://en.wikipedia.org/wiki/Paris_Hilton','url': 'http://en.wikipedia.org/wiki/Paris_Hilton','visibleUrl': 'en.wikipedia.org','cacheUrl': 'http://www.google.com/search?q=cache:TwrPfhd22hYJ:en.wikipedia.org','title': '<b>Paris Hilton</b> - Wikipedia, the free encyclopedia','titleNoFormatting': 'Paris Hilton - Wikipedia, the free encyclopedia','content': '[1] In 2006, she released her debut album...'},{'GsearchResultClass': 'GwebSearch','unescapedUrl': 'http://www.imdb.com/name/nm0385296/','url': 'http://www.imdb.com/name/nm0385296/','visibleUrl': 'www.imdb.com','cacheUrl': 'http://www.google.com/search?q=cache:1i34KkqnsooJ:www.imdb.com','title': '<b>Paris Hilton</b>','titleNoFormatting': 'Paris Hilton','content': 'Self: Zoolander. Socialite <b>Paris Hilton</b>...'}],'cursor': {'pages': [{'start': '0','label': 1},{'start': '4','label': 2},{'start': '8','label': 3},{'start': '12','label': 4}],'estimatedResultCount': '59600000','currentPageIndex': 0,'moreResultsUrl': 'http://www.google.com/search?oe=utf8&ie=utf8...'}},'responseDetails': null,'responseStatus': 200 }";上面就是從 Google 搜索返回的 Json 數(shù)據(jù),我們現(xiàn)在需要的是?responseData?屬性下的?results?列表中結(jié)果,而且僅僅需要結(jié)果中的?title、content?和?url?屬性值。
public class SearchResult {public string Title { get; set; }public string Content { get; set; }public string Url { get; set; } } //將 Json 文檔解析為 JObject JObject googleSearch = JObject.Parse(googleSearchText); //將獲得的 Json 結(jié)果轉(zhuǎn)換為列表 IList<JToken> results = googleSearch["responseData"]["results"].Children().ToList(); //將 Json 結(jié)果反序列化為 .NET 對(duì)象 IList<SearchResult> searchResults = new List<SearchResult>(); foreach(JToken result in results) {SearchResult searchResult = JsonConvert.DeserializeObject<SearchResult>(result.ToString());searchResults.Add(searchResult); } // Title = <b>Paris Hilton</b> - Wikipedia, the free encyclopedia // Content = [1] In 2006, she released her debut album... // Url = http://en.wikipedia.org/wiki/Paris_Hilton// Title = <b>Paris Hilton</b> // Content = Self: Zoolander. Socialite <b>Paris Hilton</b>... // Url = http://www.imdb.com/name/nm0385296/可以看到,對(duì) Json 文檔的解析基本分為以下幾步:
可以繼續(xù)通過(guò)?JToken[屬性]?獲取屬性?xún)?nèi)部的屬性值(依然為 JToken 格式)
如果屬性值為我們需要的數(shù)據(jù)對(duì)象,那么直接反序列化該對(duì)象就可以了;如果屬性值為列表(比如上面?results?屬性的值),那么就可以調(diào)用 JToken 類(lèi)的?Children()?函數(shù),獲得一個(gè)可迭代的 JEnumerable<JToken> 對(duì)象(用于迭代訪(fǎng)問(wèn)列表中的每一個(gè)對(duì)象),最后再依次反序列化列表中的對(duì)象。
?
轉(zhuǎn)載于:https://www.cnblogs.com/wphl-27/p/8358025.html
總結(jié)
以上是生活随笔為你收集整理的C#使用Json.NET解析Json的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 成都欢乐谷感恩节活动做到哪天
- 下一篇: C#中全局处理异常方式