在C#中如何使用JSON
JSON簡介
1. 什么是 JSON?
JSON(JavaScript Object Notation)是一種輕量級的數(shù)據(jù)交換格式。它的語法基于 JavaScript 對象表示法,簡單、易讀,同時被許多編程語言支持。盡管它來源于 JavaScript,但它并不依賴于 JavaScript,許多語言(如 Python、Java、C#、PHP 等)都能夠解析和生成 JSON。
常見用途:
API 數(shù)據(jù)交互:在客戶端和服務(wù)器之間傳遞數(shù)據(jù)時,JSON 是常用格式,特別是前后端交互時.
配置文件:許多應(yīng)用程序使用 JSON 來保存配置文件(例如 .json 文件)。
數(shù)據(jù)持久化:在數(shù)據(jù)庫或文件系統(tǒng)中使用 JSON 來存儲結(jié)構(gòu)化數(shù)據(jù)。
2. JSON 的基本語法結(jié)構(gòu)
JSON 的數(shù)據(jù)結(jié)構(gòu)非常簡單,主要包括以下兩種類型:
對象(Object):由花括號 {} 包圍的一組鍵值對,鍵是字符串,值可以是任何合法的 JSON 數(shù)據(jù)類型。
數(shù)組(Array):由方括號 [] 包圍的一組值,值可以是任意 JSON 類型。
示例:
{ "name": "John", "age": 30, "isStudent": false, "courses": ["Math", "Science"], "address": { "city": "New York", "zipcode": "10001" } }
JSON 的基本元素:
字符串:用雙引號包裹,如 "name": "John"
數(shù)字:可以是整數(shù)或浮點數(shù),如 "age": 30
布爾值:true 或 false
數(shù)組:一個有序的值列表,用方括號 [] 包裹
對象:一個無序的鍵值對集合,用花括號 {} 包裹
空值:null
你不難看出JSON 本質(zhì)上由三種主要元素構(gòu)成:
對象(Object):鍵值對的集合,類似于字典。JSON 對象用 {} 表示,包含鍵值對(key-value pairs),鍵必須是字符串,值可以是任意合法的 JSON 元素(如數(shù)組、對象或基本值)。
數(shù)組(Array):有序的元素集合,類似于列表或數(shù)組(不代表C#的數(shù)組,只是體現(xiàn)一個有序集合)。JSON 數(shù)組用 [] 表示,數(shù)組中的每個元素可以是任意合法的 JSON 元素(如對象、數(shù)組或基本值)。
基本值(Value):JSON 的最基礎(chǔ)元素,可以是字符串、數(shù)字、布爾值或 null。這部分?jǐn)?shù)據(jù)不能再包含其他子元素。
這很重要:因為充分分析這三種元素自身以及他們之間的關(guān)系是JSON處理的關(guān)鍵.很多JSON庫也是考慮了這三種概念實現(xiàn)的.
3. JSON 的優(yōu)勢(作用)
JSON 之所以成為數(shù)據(jù)交換的首選格式,離不開它的諸多優(yōu)勢:
輕量級:相比于 XML 等格式,JSON 占用的體積更小,結(jié)構(gòu)更為簡潔。
可讀性好:人類易讀,同時解析程序也易于編寫。
支持?jǐn)?shù)據(jù)類型豐富:可以直接表示對象、數(shù)組、字符串、數(shù)字、布爾值等常見的數(shù)據(jù)結(jié)構(gòu)。
廣泛支持:幾乎所有編程語言都提供了用于解析和生成 JSON 的庫或內(nèi)置函數(shù)。
標(biāo)準(zhǔn)化格式:JSON 的格式有明確的標(biāo)準(zhǔn),確保了跨語言、跨平臺的兼容性。
靈活性高:可以嵌套任意復(fù)雜的對象和數(shù)組,適合復(fù)雜的數(shù)據(jù)結(jié)構(gòu)。
4. JSON 的常見使用場景
API 通信
在現(xiàn)代 Web 開發(fā)中,前后端的通信常常依賴于 JSON。客戶端發(fā)送 HTTP 請求時,通常使用 JSON 格式來傳遞數(shù)據(jù),服務(wù)器也通過 JSON 格式返回數(shù)據(jù)。下面是一個簡單的例子:
請求體(客戶端向服務(wù)器發(fā)送的數(shù)據(jù)):
{ "username": "john_doe", "password": "123456" }
響應(yīng)體(服務(wù)器返回的數(shù)據(jù)):
{ "status": "success", "message": "Login successful", "token": "abcdef123456" }
配置文件
JSON 格式經(jīng)常用于存儲配置數(shù)據(jù),因為它易于閱讀和修改。例如,一個應(yīng)用程序的配置文件可能如下:
{ "app_name": "MyApp", "version": "1.0.0", "settings": { "theme": "dark", "language": "en" } }
本地數(shù)據(jù)存儲
前端開發(fā)中,JSON 常被用來在本地存儲數(shù)據(jù)(如瀏覽器的 localStorage 或 sessionStorage)。
數(shù)據(jù)序列化
當(dāng)將對象或數(shù)據(jù)結(jié)構(gòu)保存到文件或數(shù)據(jù)庫時,通常需要將其序列化為字符串格式,JSON 就是常用的序列化格式之一。
5.JSON和C#類型之間的映射關(guān)系
在 C# 中,JSON 的基本元素與相應(yīng)的數(shù)據(jù)類型有直接的對應(yīng)關(guān)系。
1. 字符串
JSON:字符串用雙引號包裹,表示文本數(shù)據(jù)。
示例:"name": "John"
C# 對應(yīng)類型:string
在 C# 中,JSON 的字符串類型直接映射為 string 類型。
示例:
string name = "John";
2. 數(shù)字
JSON:數(shù)字可以是整數(shù)或浮點數(shù),表示數(shù)值類型的數(shù)據(jù)。
示例:"age": 30
C# 對應(yīng)類型:int、float、double
在 C# 中,整數(shù)可以映射為 int,浮點數(shù)可以映射為 float 或 double,根據(jù)具體需要選擇類型。
示例:
int age = 30; float price = 29.99f; double pi = 3.14159;
3. 布爾值
JSON:布爾值表示為 true 或 false。
示例:"isStudent": false
C# 對應(yīng)類型:bool
在 C# 中,布爾值映射為 bool 類型。
示例:
bool isStudent = false;
4. 數(shù)組
JSON:數(shù)組是一個有序的值列表,用方括號 [] 包裹,數(shù)組中的每個元素可以是任意 JSON 類型。
示例:"courses": ["Math", "Science"]
C# 對應(yīng)類型:List<T> 或數(shù)組 T[]
在 C# 中,JSON 數(shù)組可以映射為 List<T>(泛型列表)或者普通數(shù)組 T[],其中 T 是數(shù)組中元素的類型。
示例:
List<string> courses = new List<string> { "Math", "Science" }; // 或者 string[] coursesArray = { "Math", "Science" };
5. 對象
JSON:對象是一個無序的鍵值對集合,用花括號 {} 包裹,每個鍵必須是字符串,值可以是任意 JSON 類型。
示例:"address": { "city": "New York", "zipcode": "10001" }
C# 對應(yīng)類型:自定義類或 Dictionary<string, T>
在 C# 中,JSON 對象可以映射為自定義類,類中的屬性對應(yīng) JSON 對象中的鍵值對。也可以使用 Dictionary<string, T> 來表示鍵值對集合,其中 T 表示值的類型。
示例(使用自定義類):
class Address { public string City { get; set; } public string Zipcode { get; set; } } Address address = new Address { City = "New York", Zipcode = "10001" };
示例(使用字典):
Dictionary<string, string> address = new Dictionary<string, string> { { "city", "New York" }, { "zipcode", "10001" } };
6. 空值
JSON:空值表示為 null。
示例:"middleName": null
C# 對應(yīng)類型:null
在 C# 中,JSON 的 null 對應(yīng) C# 中的 null 值。它可以應(yīng)用于任何可空類型(如引用類型和 Nullable<T>)。
在 C# 中,JSON 的基本元素可以映射為相應(yīng)的 C# 數(shù)據(jù)類型。這種映射使得我們可以輕松處理 JSON 數(shù)據(jù),并與 C# 中的對象和類型進(jìn)行交互。
6. 如何處理 JSON 數(shù)據(jù)
什么是序列化/反序列化
我們首先要先鋪墊一下什么是序列化/反序列化
序列化和反序列化是將對象和數(shù)據(jù)在不同格式之間轉(zhuǎn)換的過程,主要用于數(shù)據(jù)持久化、網(wǎng)絡(luò)傳輸?shù)葓鼍?在C#中我們的數(shù)據(jù)一般以對象形式存儲在內(nèi)存中,但是內(nèi)存數(shù)據(jù)不能持久保存,你關(guān)機后或者程序關(guān)閉時數(shù)據(jù)就沒了,那我們怎么把數(shù)據(jù)保存下來呢?
答案就是序列化,我們常用的就是將對象序列化為JSON(當(dāng)然不止JSON,只是JSON更常用),這樣我們再將其(這個其說的更清晰點就是字符串,JSON絕大多數(shù)情況是以字符串形式出現(xiàn)的,只不過你可以理解為是一種有一定格式或一定規(guī)則的字符串)保存在磁盤或者通過網(wǎng)絡(luò)傳遞給其他人都很方便.
理所當(dāng)然的JSON轉(zhuǎn)換為內(nèi)存中的對象就是反序列化,常見的情景就是讀取JSON格式的配置文件,先從磁盤讀取出來再反序列化為對象,我們就可以十分方便的操作這個對象了.
怎么做?
大多數(shù)編程語言都提供了用于解析(反序列化)和生成(序列化)JSON 數(shù)據(jù)的庫或內(nèi)置函數(shù)。
C# 提供了 System.Text.Json 和 Newtonsoft.Json(第三方庫)來處理 JSON。
我建議使用Newtonsoft.Json(NuGet Gallery | Newtonsoft.Json 13.0.3),這可以說是C#環(huán)境里最流行,最強大的一個庫,經(jīng)過二十年左右的發(fā)展支持絕大多數(shù).net環(huán)境,目前在所有nuget包中下載量中排名第一.
常見用法
1. 使用 JsonConvert.SerializeObject 方法可以將 C# 對象轉(zhuǎn)換為 JSON 字符串。
using Newtonsoft.Json; public class Person { public string Name { get; set; } public int Age { get; set; } public bool IsStudent { get; set; } } Person person = new Person { Name = "John", Age = 30, IsStudent = false }; // 序列化為 JSON string json = JsonConvert.SerializeObject(person); Console.WriteLine(json);
得到(這就是一個字符串,包括首尾的花括號在內(nèi),前面提到{}代表一個對象,里面是無序的鍵值對)
{"Name":"John","Age":30,"IsStudent":false}
2. 使用 JsonConvert.DeserializeObject<T> 可以將 JSON 字符串反序列化為 C# 對象。
//這里的\是轉(zhuǎn)義符,不是字符串自身的內(nèi)容 string json = "{\"Name\":\"John\",\"Age\":30,\"IsStudent\":false}"; // 反序列化為對象 Person person = JsonConvert.DeserializeObject<Person>(json); Console.WriteLine(person.Name); // 輸出 "John" Console.WriteLine(person.Age); // 輸出 30
3. 將 JSON 數(shù)組轉(zhuǎn)換為 C# 集合(如 List<T>)。
string jsonArray = "[{\"Name\":\"John\",\"Age\":30},{\"Name\":\"Jane\",\"Age\":25}]"; // 反序列化為 List<Person> List<Person> people = JsonConvert.DeserializeObject<List<Person>>(jsonArray); foreach (var person in people) { Console.WriteLine($"{person.Name}, {person.Age}"); }
John, 30
Jane, 25
4. 處理嵌套對象
如果 JSON 中包含嵌套對象,Newtonsoft.Json 可以自動反序列化嵌套結(jié)構(gòu)。
public class Address { public string City { get; set; } public string Zipcode { get; set; } } public class Person { public string Name { get; set; } public Address Address { get; set; } } string nestedJson = "{\"Name\":\"John\",\"Address\":{\"City\":\"New York\",\"Zipcode\":\"10001\"}}"; // 反序列化嵌套的 JSON Person person = JsonConvert.DeserializeObject<Person>(nestedJson); Console.WriteLine($"{person.Name} lives in {person.Address.City}, {person.Address.Zipcode}");
5.JToken,JObject,JArray,JValue
上面提到JSON的基本組成元素:對象,數(shù)組,基本值,這對應(yīng)看newtonjson提供的JObject,JArray,JValue三種類型,哪還有一個JToken,這個JToken是三種類型抽象類型,后三者繼承自前者.
為什么提到這些類呢?因為更靈活!
你注意上面例子,我們處理一個JSON需要先聲明一個類型,有的時候我們聲明了這個類型可能極少使用,那么這個時候我們聲明一個類型似乎就有些沒必要了.
或者這個JSON數(shù)據(jù)的結(jié)構(gòu)不是固定的,或是動態(tài)的的情況下.所以我們使用上面的類型.
string jsonString = "{\"name\": \"Alice\", \"age\": 25}"; // 使用 JObject 解析 JObject obj = JObject.Parse(jsonString); // 動態(tài)訪問字段 string name = (string)obj["name"]; int age = (int)obj["age"]; Console.WriteLine($"Name: {name}, Age: {age}");
請看JSON代表一個對象,如果不常用這個類型,那么我們直接認(rèn)為它是一個JObject類型.這樣我們轉(zhuǎn)為JObject類型,再使用索引器直接拿到我們需要的數(shù)據(jù).
上述我們知道這是一個對象,所以我們使用JObject類型,那么我們連這個也不知道呢?無妨!掏出我們的JToken類型,這個類型是三個子類的父類,包含所有子類的行為,能夠代表所有的JSON概念,無論它是對象,數(shù)組,還是基本值.
using Newtonsoft.Json.Linq; string jsonString = @"{ 'person': { 'name': 'Alice', 'age': 25, 'address': { 'city': 'Wonderland', 'zipcode': '12345' }, 'phones': ['123-456-7890', '987-654-3210'] } }"; // 解析為 JToken JToken token = JToken.Parse(jsonString); // 動態(tài)訪問嵌套字段 string name = (string)token["person"]["name"]; string city = (string)token["person"]["address"]["city"]; string phone = (string)token["person"]["phones"][0]; Console.WriteLine($"Name: {name}, City: {city}, First Phone: {phone}");
using Newtonsoft.Json.Linq; string jsonString = @"{ 'name': 'Alice', 'age': 25, 'address': { 'city': 'Wonderland', 'zipcode': '12345' }, 'hobbies': ['reading', 'chess', 'running'] }"; // 使用 JToken 解析 JToken token = JToken.Parse(jsonString); // 動態(tài)訪問對象中的字段 string name = (string)token["name"]; int age = (int)token["age"]; // 動態(tài)訪問嵌套對象 string city = (string)token["address"]["city"]; string zipcode = (string)token["address"]["zipcode"]; // 動態(tài)訪問數(shù)組中的元素 string firstHobby = (string)token["hobbies"][0]; string secondHobby = (string)token["hobbies"][1]; // 輸出結(jié)果 Console.WriteLine($"Name: {name}, Age: {age}"); Console.WriteLine($"City: {city}, Zipcode: {zipcode}"); Console.WriteLine($"First Hobby: {firstHobby}, Second Hobby: {secondHobby}");
類型轉(zhuǎn)換(對于JToken或它的子類)
Newtonsoft.Json 不僅支持通過類型強制轉(zhuǎn)換訪問 JSON 數(shù)據(jù),還提供了更加便捷的方法來進(jìn)行類型轉(zhuǎn)換。這些方法能夠避免類型強制轉(zhuǎn)換時潛在的異常風(fēng)險,并提供更清晰的代碼表達(dá)。
Newtonsoft.Json 提供了以下常用的類型轉(zhuǎn)換方法
1.Value<T>() 方法(適用于基本類型)
Value<T>() 是 JToken 提供的一個泛型方法,能夠安全地將 JToken 的值轉(zhuǎn)換為指定的類型。如果類型轉(zhuǎn)換失敗,它不會拋出異常,而是返回類型的默認(rèn)值。
適用于想要避免顯式的類型強制轉(zhuǎn)換,并且希望代碼更簡潔、安全的場景。
JToken token = JToken.Parse(@"{ 'name': 'Alice', 'age': 25 }"); string name = token["name"].Value<string>(); // 安全的類型轉(zhuǎn)換 int age = token["age"].Value<int>(); // 轉(zhuǎn)換為 int Console.WriteLine($"Name: {name}, Age: {age}");
使用 Value<T>() 進(jìn)行轉(zhuǎn)換時,如果值不存在或者轉(zhuǎn)換失敗,它會返回類型的默認(rèn)值(如 string 會返回 null,int 會返回 0),不會像類型強制轉(zhuǎn)換那樣拋出異常。
2.ToObject<T>() 方法
ToObject<T>() 是另一個常用的方法,允許將 JToken 轉(zhuǎn)換為一個具體的對象或類型。它適用于你希望將 JSON 數(shù)據(jù)反序列化為 C# 的具體類型(如類或結(jié)構(gòu)體)的場景。
ToObject<T>() 方法通過反序列化來進(jìn)行轉(zhuǎn)換,因此適合用于復(fù)雜的數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)換。
// 定義一個類與 JSON 數(shù)據(jù)對應(yīng) public class Person { public string Name { get; set; } public int Age { get; set; } } JToken token = JToken.Parse(@"{ 'name': 'Alice', 'age': 25 }"); // 將 JToken 反序列化為具體的 Person 對象 Person person = token.ToObject<Person>(); Console.WriteLine($"Name: {person.Name}, Age: {person.Age}");
適合處理復(fù)雜的 JSON 數(shù)據(jù)結(jié)構(gòu),能夠?qū)⒄麄€ JSON 結(jié)構(gòu)直接轉(zhuǎn)換為一個 C# 對象。
它的靈活性使得你可以輕松地從 JSON 數(shù)據(jù)中創(chuàng)建 C# 類對象,而不用手動提取每一個字段。
3.TryGetValue<T>(out T result) 方法
這是一個較為安全的訪問方式,TryGetValue 嘗試從 JToken 中獲取指定類型的值,并通過返回布爾值來指示是否成功獲取。
它適合在不確定 JSON 數(shù)據(jù)結(jié)構(gòu)或類型時,安全地進(jìn)行轉(zhuǎn)換操作,避免拋出異常。
JToken token = JToken.Parse(@"{ 'name': 'Alice', 'age': 'not an integer' }"); // 嘗試安全獲取值 int age; bool success = token["age"].TryGetValue<int>(out age); if (success) { Console.WriteLine($"Age: {age}"); } else { Console.WriteLine("Failed to get a valid integer for age."); }
安全的類型轉(zhuǎn)換方式,適合在 JSON 數(shù)據(jù)不可靠或結(jié)構(gòu)復(fù)雜時使用。
它通過 out 參數(shù)來返回結(jié)果,能夠避免異常。
強制類型轉(zhuǎn)換 vs 提供的方法
強制類型轉(zhuǎn)換(Explicit Casting)
允許直接進(jìn)行強制類型轉(zhuǎn)換,比如 (string)token["name"] 或 (int)token["age"]。這種方式比較簡潔,但是如果類型不匹配或值不存在,會拋出異常。
總結(jié)
Value<T>() 方法:提供了安全的類型轉(zhuǎn)換方式,不會拋出異常,適合處理簡單的數(shù)據(jù)訪問場景,代碼簡潔。
ToObject<T>() 方法:適合將 JSON 直接轉(zhuǎn)換為 C# 對象,特別是對于復(fù)雜的 JSON 結(jié)構(gòu),能夠減少手動提取每個字段的工作量。
TryGetValue<T>() 方法:提供一種安全的方式來獲取 JSON 數(shù)據(jù)中的值,適合在不確定數(shù)據(jù)結(jié)構(gòu)或類型的情況下使用,防止異常的發(fā)生。
到此這篇關(guān)于在C#中使用JSON的文章就介紹到這了,更多相關(guān)C#使用JSON內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#通過XML節(jié)點屬性/屬性值讀取寫入XML操作代碼實例
本文主要介紹C#通過XML節(jié)點屬性、屬性值對XML的讀取,寫入操作,大家參考使用吧2013-11-11