C#使用Json.NET解析Json

本文轉載自?http://xiaosheng.me/2016/10/01/article25/

最近在 C# 項目中需要使用到 Json 格式的數據,我簡單上網搜索了一下,基本上有兩種操作 Json 數據的方法:

  • 使用 Windows 系統自帶的類
  • 使用第三方的包

本著“第三方包一定有比系統自帶類優秀地方,否則就不會存在”的原則,再加上?JavaScriptSerializer、DataContractJsonSerializer?等這些自帶類庫使用起來很麻煩,我毫不猶豫地就選擇了在 Json 操作方面小有名氣的?Json.NET。Json.NET 自己也做了與自帶類庫的比較,詳情可以見?Json.NET vs .NET Serializers?和?Json.NET vs Windows.Data.Json。

Json.NET 是一個 Newtonsoft 編寫的開源類庫包,你可以直接到 Github 上查看項目的源碼和說明。Json.NET 提供了大量對于 Json 數據的操作方法,他們使用起來非常簡單,而且執行效率很高。

.NET 對象的序列化和反序列化

1. 普通對象的序列化和反序列化

JsonConvert?是 Json.NET 中的一個數據轉換類,提供了用于 .NET 對象序列化和反序列化的方法?SerializeObject()?和?DeserializeObject()。在通常情況下,我們也只需要使用這兩個方法就足以完成任務了。

比如說,我們現在定義了一個學生類 Student:

class Student //學生類
{public int Id { get; set;} //學號public string Name { get; set;} //姓名public double[] Scores { get; set;} //成績
}

現在我們創建一個學生類對象,并使用?JsonConvert?類提供的?SerializeObject()?方法將它轉換到 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]}

可以看到在序列化的過程中,JsonConvert?會將 .NET 對象中的變量名轉換為 Json 中的“屬性”,同時將變量的值復制為 Json 的“屬性值”。接下來,我們嘗試將 Json 字符串轉換為?Student?對象,使用?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

可以看到,創建的學生對象?student?的 Json 字符串被順利地解析成了 Student 對象。在調用?DeserializeObject()?方法進行反序列化時,最好使用帶泛型參數的重載方法。

如果在調用 DeserializeObject() 時不指定對象類型,JsonConvert 會默認轉換為 Object 對象。

集合的序列化和反序列化

上面我們已經簡單測試了 JsonConvert 提供的?SerializeObject()?和?DeserializeObject()?方法,完成了 .NET 對象的序列化和反序列化。

C# 項目中,除了自定義的類型外,集合(Collections)也是經常會使用的數據類型,包括列表、數組、字典或者我們自定義的集合類型。我們同樣可以使用之前使用的?SerializeObject()?和?DeserializeObject()?方法來完成集合的序列化和反序列化。

為了使轉換后的結果更加易讀,我指定轉換后的 Json 字符串帶縮進。通過向 SerializeObject() 方法傳遞進第二個參數 Formatting 實現。
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
//    ]
//  }
//]

接下來我們對上面生成的 Json 字符串進行反序列化,解析出原有的 Student 類型列表。同樣,我們需要使用帶泛型參數的?DeserializeObject()?方法,指定 JsonConvert 解析的目標類型。

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 對象擁有統一類型的屬性和屬性值,我們還可以把 Json 字符串反序列化為 .NET 中的字典,Json 對象的“屬性”和“屬性值”會依次賦值給字典中的 Key 和 Value。下面我舉一個簡單的例子:

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

解析復雜的 Json 字符串

如今大量的 Web API 為我們編寫復雜程序提供了極大的方便,例如百度地圖 API、圖靈機器人 API等等,利用這些 Web 應用程序我們可以充分發揮云服務的優勢,開發出大量有趣的應用。

Web API 通常返回 Json 或 XML 格式的檢索數據,由于 Json 數據量更小,所以目前大多數情況下我們都選擇返回 Json 格式的數據。

如果返回的 Json 文檔很大,而我們僅僅需要其中的一小部分數據。按照之前的方法,我們必須首先定義一個與 Json 對象對應的 .NET 對象,然后反序列化,最后才能從對象中取出我們需要的數據。而有了 Json.NET,這個任務就很容易實現了,我們可以局部地解析一個 Json 對象。

下面以獲取 Google 搜索結果為例,簡單演示一下對復雜結構 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 數據,我們現在需要的是?responseData?屬性下的?results?列表中結果,而且僅僅需要結果中的?titlecontent?和?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 結果轉換為列表
IList<JToken> results = googleSearch["responseData"]["results"].Children().ToList();
//將 Json 結果反序列化為 .NET 對象
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/

可以看到,對 Json 文檔的解析基本分為以下幾步:

  1. 將 Json 文檔轉換為 JObject 對象
  2. 使用JObject[屬性]獲取 JObject 對象中某個屬性的值(JToken 格式)
    可以繼續通過?JToken[屬性]?獲取屬性內部的屬性值(依然為 JToken 格式)
  3. 將 JToken 格式的屬性值反序列化為 .NET 對象

如果屬性值為我們需要的數據對象,那么直接反序列化該對象就可以了;如果屬性值為列表(比如上面?results?屬性的值),那么就可以調用 JToken 類的?Children()?函數,獲得一個可迭代的 JEnumerable<JToken> 對象(用于迭代訪問列表中的每一個對象),最后再依次反序列化列表中的對象。

?

轉載于:https://www.cnblogs.com/wphl-27/p/8358025.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/390292.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/390292.shtml
英文地址,請注明出處:http://en.pswp.cn/news/390292.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

現在JavaScript日期–如何在JavaScript中獲取當前日期

Many applications you build will have some sort of a date component, whether its the creation date of a resource, or the timestamp of an activity. 您構建的許多應用程序都將具有某種日期組件&#xff0c;無論是資源的創建日期還是活動的時間戳。 Dealing with date…

233. 數字 1 的個數

給定一個整數 n&#xff0c;計算所有小于等于 n 的非負整數中數字 1 出現的個數。 示例 1&#xff1a; 輸入&#xff1a;n 13 輸出&#xff1a;6 示例 2&#xff1a; 輸入&#xff1a;n 0 輸出&#xff1a;0 解題思路 正確性證明 例如&#xff1a;對于n3015&#xff0c…

Linux串口設置參數

為什么80%的碼農都做不了架構師&#xff1f;>>> 在Linux環境下&#xff0c;串口名從ttyS0開始依次是ttyS1、ttyS2等。在本程序中&#xff0c;使用ttyS0作為通信串口。在打開ttyS0的時候選項 O_NOCTTY 表示不能把本串口當成控制終端&#xff0c;否則用戶的鍵盤輸入信…

STM32F013 十元板

我大拇指般大小。STM32F103C8T6&#xff0c;64K Flash&#xff0c;20K RAM&#xff0c;m3的核。十元&#xff0c;應該是價格極限了吧。 通過USB供電&#xff08;5V&#xff09;&#xff0c;也可以排針3.3V供電。可惜沒有引出5V排針。USB口可以供電和USB通訊&#xff0c;沒有USB…

如何在Python中建立和訓練K最近鄰和K-Means集群ML模型

One of machine learnings most popular applications is in solving classification problems.機器學習最流行的應用之一是解決分類問題。 Classification problems are situations where you have a data set, and you want to classify observations from that data set in…

552. 學生出勤記錄 II

552. 學生出勤記錄 II 可以用字符串表示一個學生的出勤記錄&#xff0c;其中的每個字符用來標記當天的出勤情況&#xff08;缺勤、遲到、到場&#xff09;。記錄中只含下面三種字符&#xff1a; ‘A’&#xff1a;Absent&#xff0c;缺勤 ‘L’&#xff1a;Late&#xff0c;遲…

C/C++中計算函數運行時間

#include<stdio.h> #include<time.h> clock_t start,stop;//clock_t 是clock&#xff08;&#xff09;函數返回變量的類型 double duration;//記錄被測函數的運行時間&#xff0c;以秒為單位 int main() { startclock();//開始計時 MyFunction();//把被測函數加在這…

作為一名前端開發工程師,你必須掌握的WEB模板引擎:Handlebars

為什么需要使用模板引擎&#xff1f; 關于為什么要使用模板引擎&#xff0c;按照我常說的一句話就是&#xff1a;不用重復造輪子了。 簡單來說&#xff0c;模板最本質的作用是“變靜為動”&#xff0c;一切利于這方面的都是優勢&#xff0c;不利于的都是劣勢。要想很好地實現“…

extjs 實用開發指南_如何提出有效問題:針對開發人員的實用指南

extjs 實用開發指南Learning is a journey that never ends. At every point in your career, you will keep learning, re-learning, and un-learning. 學習是一個永無止境的旅程。 在職業生涯的每個階段&#xff0c;您都會不斷學習&#xff0c;重新學習和不學習。 The abil…

LOJ 6270

最近&#xff08;一直&#xff09;有點&#xff08;很&#xff09;蠢 按照區間大小排序做區間包含多少區間的話 只用考慮 左端點比當前左端點小的和右端點比當前右端點大的&#xff0c;因為不可能同時滿足 關于K&#xff0c;就在做到K的時候減一下就好了&#xff0c;一直傻逼在…

Zabbix3.4安裝詳細步驟

Zabbix3.4安裝的詳細步驟一、zabbix介紹現在大多數公司都會用到監控軟件&#xff0c;主流的監控軟件就是Zabbix了&#xff0c;當然還會有Nagios等其他的軟件&#xff1a;zabbix是一個基于WEB界面的提供分布式系統監視以及網絡監視功能的企業級的開源解決方案。zabbix能監視各種…

軟件自學成才到公司要學歷嗎_作為一名自學成才的移動開發人員,我在旅途中學到了什么

軟件自學成才到公司要學歷嗎In this post, Ill share my entire journey about how I became a professional mobile developer.在這篇文章中&#xff0c;我將分享我如何成為一名專業的移動開發人員的整個過程。 I hope that reading about my experience will help you refle…

cs231n---語義分割 物體定位 物體檢測 物體分割

1 語義分割 語義分割是對圖像中每個像素作分類&#xff0c;不區分物體&#xff0c;只關心像素。如下&#xff1a; &#xff08;1&#xff09;完全的卷積網絡架構 處理語義分割問題可以使用下面的模型&#xff1a; 其中我們經過多個卷積層處理&#xff0c;最終輸出體的維度是C*H…

http協議內容

前言&#xff1a; http協議&#xff1a; 對瀏覽器客戶端 和 服務器端 之間數據傳輸的格式規范http1.0&#xff1a;當前瀏覽器客戶端與服務器端建立連接之后&#xff0c; 只能發送一次請求&#xff0c;一次請求之后連接關閉。 http1.1&#xff1a;當前瀏覽器客戶端與服務器端建…

array_combine()

轉載于:https://www.cnblogs.com/xiaobiaomei/p/8392728.html

CSS外邊距(margin)重疊及防止方法

#css外邊距margin重疊及防止方法CSS外邊距(margin)重疊及防止方法 #1-什么是外邊距margin重疊1. 什么是外邊距(margin)重疊 外邊距重疊是指兩個或多個盒子(可能相鄰也可能嵌套)的相鄰邊界(其間沒有任何非空內容、補白、邊框)重合在一起而形成一個單一邊界。 #2-相鄰marign重疊的…

composer windows安裝

一.前期準備: 1.下載安裝包,https://getcomposer.org/download/ 2.在php.ini文檔中打開extensionphp_openssl.dll 3.下載php_ssh2.dll、php_ssh2.pdb,http://windows.php.net/downloads/pecl/releases/ssh2/0.12/ 4.把php_ssh2.dll、php_ssh2.pdb文件放php的ext文件夾 5.重啟ap…

spring整合mybatis采坑

本來這個錯誤是整合spring和mybatis遇到的錯誤&#xff0c;但是一直沒有解決&#xff0c;但是在做SpringMVC時也了出現了這樣的錯誤org.springframework.beans.factory.BeanCreationException: Error creating bean with name sqlSessionFactory defined in class path resourc…

處理測試環境硬盤爆滿

測試環境經常會收到這類告警 第一步 登陸機器查看硬盤使用 執行df 好吧,使用情況真不妙,根目錄占用過大 第二步 確定哪個文件太大或者文件過多 進入爆滿的目錄,如這里是根目錄 cd / 然后找下面哪個文件夾或者文件太大,有幾種方式: 1.dusudo du -h --max-depth1 | sort -hr 越前…

LeetCode-46. Permutations

一、問題描述 就是全排列問題。 二、問題解決 應該哪一本數據結構的書上都有講了。 void get_permute(vector<int>& nums, int pos, vector<vector<int>>& result) {if (nums.size() pos) {result.push_back(nums);return;}for (int i pos; i <…