巧用 JSON序列化/反序列化,輕松實現C#對象映射
當前位置:點晴教程→知識管理交流
→『 技術文檔交流 』
一、引言簡述在?C#編程的世界里,對象映射是一項十分重要且常用的操作,而利用JSON序列化/反序列化來實現對象映射更是有著廣泛的應用場景。比如說,當我們需要與外部系統進行數據交互時,常常要把C#中的對象轉換為JSON格式的數據發送出去,這就涉及到對象的序列化;而接收到外部傳來的JSON數據后,又需要將其還原成C#對象以便后續處理,這就是反序列化的過程了。再比如,在存儲數據或者對數據進行傳輸封裝等操作時,這種基于JSON的對象映射方式也能幫我們更便捷地處理數據。 今天,我就來給大家詳細分享一下利用?JSON序列化/反序列化輕松實現對象映射的具體步驟,相信掌握了這些內容,會讓大家在面對相關開發需求時更加得心應手,下面咱們就正式開始吧。 二、JSON序列化/反序列化基礎知識JSON數據格式簡介JSON(JavaScript Object Notation)是一種輕量級的數據交換格式,它基于JavaScript編程語言的一個子集,但因其文本格式清晰簡潔,被廣泛用于數據交換和存儲。 JSON所支持的數據結構及常見表現形式如下: ?對象(Object):對象是由鍵值對組成的無序集合,鍵是字符串,值可以是任何類型,包括對象和數組。對象由一對花括號{ } 包圍,鍵和值之間用冒號: 分隔,鍵值對之間用逗號, 分隔。例如:{"name": "John Doe", "age": 30, "isMarried": false, "children": ["Alice", "Bob"]}。需要注意的是,JSON中對象的屬性名必須用雙引號,屬性值如果是字符串也必須用雙引號,只要涉及到字符串,就必須使用雙引號,并且不支持undefined。 ?數組(Array):數組是值的有序集合,每個值可以是任何類型,包括對象和數組。數組由一對方括號[ ] 包裹,值之間用逗號, 分隔。比如:["apple", "banana", "cherry"]。 ?字符串(String):JSON字符串是由雙引號" " 包圍的?Unicode字符序列,使用反斜杠\ 轉義,像{"name": "Apifox", "city": "Guangzhou"} 中的"name" 和"city" 就是字符串的示例。 ?數字(Number):可以是整數或浮點數,例如{"age": 30, "weight": 65.5} 中的30 和65.5 分別是整數和浮點數,數字不需要雙引號包圍。 ?布爾值(Boolean):只有兩個取值,即true 和false,如{"isStudent": true, "isEmployed": false} 中的isStudent 和isEmployed 取值示例,同樣不需要雙引號包圍。 ?null:表示一個空值,像{"middleName": null} 里的middleName 的值就是null,也無需雙引號包圍。 這些結構還可以相互嵌套,形成復雜的?JSON數據格式,以此來滿足不同場景下的數據表示需求。 C#中相關命名空間及類庫介紹在?C#里,常用于JSON序列化/反序列化操作的有以下幾個重要的命名空間及對應的類庫: 1.System.Web.Script.Serialization: 這個命名空間下的JavaScriptSerializer 類可用于?JSON的序列化和反序列化。例如,以下是簡單的代碼示例展示其使用方式:
不過,該類在處理DateTime 類型數據的序列化時可能存在一些小問題,比如序列化后的時間可能會出現偏差等情況。 2.Newtonsoft.Json(JSON.NET): 這是一個成熟且使用廣泛的第三方庫,擁有豐富的功能和強大的靈活性,多年來在.NET社區中被廣泛接受和使用。它支持弱類型轉換,并且提供了一些更高級的功能,比如完全自定義的序列化和反序列化邏輯,能處理循環引用、自定義轉換器、忽略屬性等等,可以方便地應對一些復雜的JSON數據場景。使用前需要通過NuGet進行安裝,示例代碼如下:
3.System.Text.Json: 它是.NET Core的一部分,在創建跨平臺應用程序時,不需要額外的依賴項,使用起來較為方便。并且在性能方面進行了優化,通常比Newtonsoft.Json 更快,利用了新的讀寫?API,采用更高效的內部實現,提供了更好的性能和內存利用率。同時,它還提供了一些簡化的API,在處理簡單的JSON數據時更容易操作,不過默認是強類型轉換,比如實體類定義的是字符串,JSON字符串返回的是整型,轉換時會報錯。示例代碼如下:
開發者可以根據具體的項目需求、數據復雜程度以及性能等方面的考量,來選擇合適的命名空間及類庫進行?JSON序列化/反序列化操作。 三、利用?System.Runtime.Serialization.Json實現對象映射類的準備與標記當我們使用System.Runtime.Serialization.Json 這個命名空間來進行對象映射相關操作時,有個重要的前提要求,那就是參與序列化和反序列化的類需要進行特定的標記。 具體來說,類需要標記為[DataContract],它相當于一種契約,是使用DataContractJsonSerializer 序列化和反序列化必須要添加的標識。而對應類中的屬性,則要標記為[DataMember],只有標記了的屬性才會參與到序列化和反序列化的過程當中。 以下面這個簡單的Student 類為例來看看具體如何標記:
在上述代碼中,Student 類標記了[DataContract],其內部的ID、Name、Age、Sex 這幾個屬性都標記了[DataMember],這樣在后續利用System.Runtime.Serialization.Json 相關功能時,這個類的對象就可以順利地進行序列化和反序列化操作了,將類和屬性按照這樣的要求標記好,是利用該方式實現對象映射的基礎準備工作哦。 序列化操作步驟接下來詳細講講利用DataContractJsonSerializer 類將?C#對象序列化為JSON字符串的具體流程。 第一步,我們需要先創建好要進行序列化的對象。比如還是以剛才定義的Student 類為例,我們可以這樣創建一個Student 類的實例:
第二步,實例化DataContractJsonSerializer 序列化器,這里要傳入我們想要序列化的對象類型,代碼如下:
第三步,創建一個MemoryStream 內存流對象,用于后續將序列化之后的?JSON格式數據寫入到這個流當中,像這樣:
第四步,利用剛才實例化好的序列化器的WriteObject 方法,把我們創建的對象寫入到內存流中,對應代碼為:
第五步,要從內存流中讀取數據,在讀取之前需要先將內存流的位置設置為?0,也就是起始位置,然后創建StreamReader 讀取流中的數據,并將讀取到的內容轉換為字符串,代碼示例如下:
最后,我們就可以得到序列化后的?JSON字符串了。完整的代碼整合起來就是這樣:
假如上述代碼中Student 類對象的各個屬性值分別是ID = 01,Name = "釘釘",Sex = "男",Age = 1,那最終序列化得到的?JSON字符串結果可能類似這樣:{"ID":1,"Name":"釘釘","Age":1,"Sex":"男"}(實際結果會根據具體類結構和屬性值情況有所不同哦),這樣就完成了從?C#對象到JSON字符串的序列化操作啦。 反序列化操作步驟下面講解將?JSON字符串反序列化為C#對象的具體操作步驟。 首先,我們得有一個?JSON字符串,這個字符串可以是從外部獲取到的數據,比如從網絡接口返回的JSON格式的數據內容等,假設我們現在已經有了這樣一個JSON字符串變量toDes,示例如下:
第一步,要實例化DataContractJsonSerializer 反序列化器,同樣需要傳入要反序列化的目標對象類型,代碼如下:
第二步,利用反序列化器的ReadObject 方法,從內存流中讀取數據并還原成對應的?C#對象,像這樣:
整合起來完整的反序列化代碼示例如下:
當執行完上述反序列化操作后,如果反序列化成功,我們就可以得到一個還原后的Student 類對象,并且可以通過訪問對象的屬性來獲取相應的值,例如像代碼中那樣輸出ID、Name、Age、Sex 等屬性的值,以此來驗證反序列化的結果是否符合預期哦,這樣就完成了從?JSON字符串到C#對象的反序列化過程啦。 四、借助?System.Text.Json進行對象映射
類的準備特點在使用System.Text.Json 進行對象映射相關操作時,其類的準備與之前介紹的一些方式有所不同。它并不依賴像System.Runtime.Serialization.Json 中那樣特定的屬性標記(如[DataContract] 和[DataMember] 等)來決定哪些屬性參與序列化和反序列化。 System.Text.Json 主要依據公共屬性和字段的可見性來進行序列化。只要類中的屬性是公共的(使用public 修飾符),在默認情況下就會被包含在序列化和反序列化的過程中。例如,我們定義如下一個簡單的Employee 類:
在上述代碼中,Name、Age 和Department 這幾個公共屬性,在使用System.Text.Json 進行序列化時,都會自動被處理,不需要額外添加特殊的標記。這使得在一些簡單的場景下,類的準備工作更加簡潔直觀,減少了代碼中額外的屬性標記負擔。不過,如果想要對序列化和反序列化的過程進行更精細的控制,比如忽略某些屬性或者改變屬性序列化后的名稱等,就需要借助System.Text.Json 提供的相關配置選項和特性來實現啦,后續我們會詳細講到哦。 序列化操作流程下面來詳細說說利用System.Text.Json 進行對象序列化的具體操作流程哈。 首先,我們要創建好需要序列化的對象,就像前面定義的Employee 類,我們可以這樣實例化一個對象:
接著,配置序列化相關的選項,這一步是通過JsonSerializerOptions 類來完成的。這個類提供了很多可配置的屬性,例如: ?WriteIndented 屬性:如果將其設置為true,那么序列化后的?JSON字符串會進行格式化,有縮進和換行,方便閱讀查看;若設置為false(默認值),則序列化后的?JSON字符串是緊湊的,沒有多余的空格和換行哦。示例代碼如下:
?PropertyNamingPolicy 屬性:可以用來指定屬性名稱在序列化后的命名規則,比如設置為JsonNamingPolicy.CamelCase,那么原本在?C#類中采用帕斯卡命名法(首字母大寫)的屬性名,在序列化后的JSON字符串中就會變成駝峰命名法(首字母小寫)形式啦。像這樣:
配置好選項后,就可以執行序列化操作了,調用JsonSerializer.Serialize 方法,將對象和配置選項(如果有配置的話)作為參數傳入,示例代碼如下:
假設我們前面創建的Employee 對象屬性值分別是Name = "小李",Age = 28,Department = "研發部",并且配置了WriteIndented = true 和PropertyNamingPolicy = JsonNamingPolicy.CamelCase,那最終序列化得到的?JSON字符串結果可能類似這樣:
這樣就完成了利用System.Text.Json 把?C#對象序列化為JSON字符串的操作啦,整個過程還是比較清晰明了的哦。 反序列化操作流程接下來講講如何通過System.Text.Json 將?JSON字符串反序列化為C#對象呀。 第一步,我們得先有一個?JSON字符串,這個字符串可能是從外部接口獲取到的,或者是從文件中讀取出來的數據等等,比如下面這樣一個示例JSON字符串:
在?C#代碼中可以這樣定義這個字符串變量:
然后,同樣需要配置反序列化相關的選項,也是通過JsonSerializerOptions 類來進行配置哦,配置的方法和序列化時類似,例如設置屬性名稱大小寫不敏感等情況(如果有需要的話),像這樣:
接著,就可以調用JsonSerializer.Deserialize 方法來執行反序列化操作啦,需要指定要反序列化的目標對象類型,示例代碼如下:
如果反序列化成功,我們就可以通過訪問deserializedEmp 對象的各個屬性來獲取相應的值啦,比如輸出對象的屬性值看看:
這樣,就完成了從?JSON字符串到C#對象的反序列化過程哦,通過System.Text.Json 進行序列化和反序列化操作,在很多項目中都能方便地實現數據的轉換和處理呢。 五、使用?Newtonsoft.Json(Json.NET)完成對象映射程序包引用與命名空間導入在?C#項目中若要使用Newtonsoft.Json(Json.NET)庫來進行?JSON序列化/反序列化操作,首先需要引用相應的程序包并導入對應的命名空間哦。 引用程序包的常見方式是通過?NuGet程序包管理器,不同的開發工具操作略有不同。例如在Visual Studio中,可以點擊“工具- NuGet包管理器-程序包管理器控制臺”,然后在控制臺輸入命令“Install-Package Newtonsoft.Json”(不同版本可能命令稍有差異,比如有的版本后面會跟具體版本號等),回車后NuGet就會自動下載并安裝Newtonsoft.Json程序包到項目中啦,像這樣就引用成功了哦。 在成功引用程序包后,我們還需要在代碼文件中導入對應的命名空間,這樣才能使用該庫提供的各種類和方法呀,導入的語句是“using Newtonsoft.Json;”,將這條語句添加到代碼文件的頂部(通常在其他using語句一起的位置哦),就可以開始使用Newtonsoft.Json相關功能進行對象映射的操作啦,下面咱們接著看看具體的序列化和反序列化示例吧。 序列化示例與特性運用接下來看看如何利用?Newtonsoft.Json中的JsonConvert.SerializeObject方法將C#對象序列化為JSON字符串哈。 咱們先定義一個簡單的類,比如下面這個表示學生信息的類:
然后創建這個類的對象,并調用?JsonConvert.SerializeObject方法進行序列化操作,示例代碼如下:
上述代碼運行后,輸出結果會是這樣的?JSON字符串格式:
在實際應用中,有時候我們可能不希望某些字段參與對象的?JSON序列化,這時候就可以使用[JsonIgnore]特性啦。例如,我們不想讓“Sex”字段被序列化,那可以修改“Student”類的定義如下:
再執行同樣的序列化操作,輸出結果就會變成這樣:
可以看到“Sex”字段就沒有出現在序列化后的JSON字符串中了哦。 還有一種情況,我們可能想在對象序列化時更換字段的輸出名稱,比如簡化字段名稱以縮短?JSON字符串的長度等,這時就可以使用[JsonProperty]特性標識字段啦。假設我們想把“Description”字段在序列化后的名稱改為“Desc”,代碼可以這樣寫:
重新執行序列化操作后,輸出結果如下:
通過這些特性的運用,我們可以更靈活地控制對象序列化后的?JSON字符串格式呢,方便滿足不同的業務需求哦。 反序列化示例與注意事項下面咱們講講如何將?JSON字符串通過JsonConvert.DeserializeObject方法反序列化為C#對象哈。 先來看個簡單的例子,假設我們有如下的?JSON字符串:
我們要把它反序列化為“Student”類的對象列表,對應的“Student”類定義如下(這里注意不要使用之前講序列化特性時那些特殊的特性標記哦,保持常規的類定義就行):
在?C#代碼中進行反序列化的操作示例如下:
上述代碼執行后,就能成功將?JSON字符串反序列化為“Student”類的對象列表,并且可以通過遍歷輸出每個對象的屬性值來驗證反序列化的結果哦,輸出結果會是這樣:
這里有個需要注意的事項哈,在進行反序列化時,類中屬性名稱要和?JSON字符串中的鍵相對應哦。如果屬性名稱不一致,那可能會導致反序列化出來的對象屬性值不正確或者出現異常情況呢。比如JSON字符串里某個鍵是“student_name”,而對應的C#類里屬性定義是“StudentName”,那就沒辦法正確賦值啦,所以在編寫代碼和設計數據結構時,要保證這種對應關系哦,這樣才能順利地完成基于Newtonsoft.Json的對象反序列化操作呀,大家可以自己動手多試試不同的示例,加深理解哦。 六、不同方法的對比與選擇建議各方法性能、功能對比在?C#開發中,常用的JSON序列化/反序列化方法有System.Runtime.Serialization.Json、System.Text.Json、Newtonsoft.Json等,它們在性能表現以及支持的功能特性方面存在一定差異。 ?System.Runtime.Serialization.Json:這是.NET Framework內置的庫,優勢在于無需額外的引用,并且支持DataContract屬性和WCF協定,比較適合在一些老項目中使用。不過,其性能相對較差,像在處理大量數據的序列化和反序列化時,效率可能不如其他幾種方式。而且它不支持一些高級功能,例如自定義轉換器,在面對復雜的JSON數據場景時,靈活性欠佳。 ?System.Text.Json:作為.NET Core的一部分,在創建跨平臺應用程序時,不需要額外的依賴項,使用起來較為方便。性能方面進行了優化,通常比Newtonsoft.Json更快,利用了新的讀寫API,采用更高效的內部實現,有更好的性能和內存利用率。在處理簡單的JSON數據時,其提供的簡化API也更容易操作,但默認是強類型轉換,比如實體類定義的是字符串,JSON字符串返回的是整型,轉換時會報錯。另外,雖然默認強類型轉換,但也可以通過自定義轉換器等方式來實現弱類型轉換,以滿足更多不同的需求。 ?Newtonsoft.Json(JSON.NET):它是一個成熟且使用廣泛的第三方庫,在.NET社區中被廣泛接受和使用。擁有豐富的功能和強大的靈活性,比如支持完全自定義的序列化和反序列化邏輯,能處理循環引用、自定義轉換器、忽略屬性等等,可以方便地應對各種復雜的JSON數據場景。不過,它相對有較大的依賴包,并且在某些場景下,性能可能會低于一些最新的庫。 根據項目場景選擇合適方法在實際的項目開發中,選擇哪種?JSON序列化/反序列化方法來實現對象映射,需要綜合考慮多個因素,以下是一些依據不同項目情況給出的選擇建議: ?基于.NET版本: ?如果是老項目,本身基于.NET Framework,且對性能要求不是特別極致,功能需求也相對常規,那么System.Runtime.Serialization.Json是可以勝任的,畢竟無需額外引用,能方便地集成到已有項目中,符合項目原本的技術棧特點。 ?若是基于.NET Core開發的新項目,特別是創建跨平臺應用程序時,System.Text.Json就比較合適了,它與.NET Core集成緊密,還自帶性能優勢以及簡化的API,方便快捷地處理常見的JSON數據操作,減少額外依賴帶來的潛在問題。 ?而無論項目基于哪種.NET版本,只要涉及到較為復雜的JSON數據處理場景,比如需要處理循環引用、要對序列化和反序列化邏輯做深度定制、或者要靈活地處理各種數據類型轉換等情況,Newtonsoft.Json就是一個很好的選擇,雖然可能依賴包稍大些,但豐富的功能可以應對各種復雜需求。 ?對性能和靈活性的需求: ?當項目對性能有較高要求,例如是大數據量處理的應用,像電商平臺的訂單數據處理、大數據系統中的數據交互等場景,優先考慮?System.Text.Json,它在處理大量數據的序列化和反序列化時效率表現突出,能夠保障系統整體的數據處理速度,避免性能瓶頸。 ?如果項目更注重靈活性,比如需要頻繁根據不同業務場景去動態調整對象序列化和反序列化的規則,像根據不同客戶端需求輸出不同格式的?JSON數據、要忽略某些屬性或者改變屬性序列化后的名稱等情況,Newtonsoft.Json的優勢就體現出來了,借助其豐富的功能特性,可以輕松實現各種自定義邏輯,滿足多變的業務需求。 ?要是項目只是處理一些簡單常規的?JSON數據交互,性能要求也不是特別高,追求簡潔方便的開發體驗,System.Text.Json同樣可以滿足,利用它默認的配置和簡單的API就能快速實現對象映射,減少開發成本和出錯概率。 七、總結內容回顧在本文中,我們詳細介紹了利用?JSON序列化/反序列化實現C#對象映射的幾種主要方法,下面來簡單回顧一下關鍵內容,幫助大家強化記憶哦。 首先是利用System.Runtime.Serialization.Json 實現對象映射,使用這個命名空間時,參與操作的類要標記[DataContract],類中的屬性需標記[DataMember],這是進行序列化和反序列化的基礎準備。序列化時,要先創建對象、實例化DataContractJsonSerializer 序列化器、創建MemoryStream 內存流對象,接著用序列化器的WriteObject 方法將對象寫入內存流,最后從內存流中讀取數據并轉換為字符串,就得到了序列化后的?JSON字符串。反序列化與之類似,先有JSON字符串,實例化反序列化器后,用ReadObject 方法從內存流中讀取數據還原成?C#對象。 System.Text.Json 進行對象映射時,類準備工作主要依據公共屬性和字段的可見性,公共屬性默認會被包含在序列化和反序列化過程中。序列化要先創建對象,通過JsonSerializerOptions 類配置相關選項,比如設置WriteIndented 屬性控制字符串格式、PropertyNamingPolicy 屬性指定屬性名稱的命名規則等,然后調用JsonSerializer.Serialize 方法執行序列化。反序列化則是先有?JSON字符串,同樣配置好JsonSerializerOptions 類(按需配置屬性名大小寫不敏感等情況),再調用JsonSerializer.Deserialize 方法還原?C#對象。 使用Newtonsoft.Json(Json.NET) 庫時,得先通過?NuGet程序包管理器引用程序包,并在代碼文件中導入using Newtonsoft.Json; 命名空間。序列化可以通過JsonConvert.SerializeObject 方法實現,還能運用特性,像[JsonIgnore] 可讓字段不參與序列化,[JsonProperty] 能更換字段的輸出名稱,使序列化更靈活。反序列化用JsonConvert.DeserializeObject 方法,不過要注意類中屬性名稱要和?JSON字符串中的鍵對應,不然可能出現賦值異常情況哦。 不同的方法各有特點,在性能、功能以及適用場景等方面都存在差異,大家可以根據實際項目情況去選擇合適的方式來進行?C#對象映射呀。 拓展與展望隨著技術的不斷發展,JSON序列化/反序列化在C#對象映射中的應用也有著廣闊的拓展空間呢。 從拓展應用方向來看,在微服務架構日益流行的當下,各個微服務之間的數據交互頻繁,利用?JSON序列化/反序列化實現對象映射可以更好地保障數據格式的統一和交互的順暢。例如,在一個電商系統的微服務架構里,商品服務、訂單服務、用戶服務等不同的微服務之間傳遞數據時,通過高效準確的對象映射,能讓數據快速在各個環節流轉,提升整個系統的協同效率。 而且,在跨平臺開發越來越普遍的趨勢下,像.NET Core支持的跨平臺應用開發場景中,System.Text.Json 這類無需額外依賴項且性能優良的方式,有望在更多類型的項目里發揮重要作用,進一步優化數據傳輸和存儲的效率。 對于想要進一步學習提升的朋友們來說,可以深入研究各個庫的高級特性和自定義功能哦。比如深入了解Newtonsoft.Json 的自定義轉換器實現原理,嘗試自己編寫復雜數據結構的轉換邏輯,應對各種特殊的業務數據需求;或者探索System.Text.Json 如何更好地結合.NET Core的其他新特性,來打造高性能、低資源占用的應用程序。 此外,多參考開源項目里對于?JSON序列化/反序列化對象映射的優秀實踐案例也是個不錯的學習途徑,從中汲取經驗,運用到自己的實際項目中。 該文章在 2024/12/19 17:56:04 編輯過 |
關鍵字查詢
相關文章
正在查詢... |