上一節我們討論了如何手動方式來處理JSON對象資料,可能你也發現了,是有些痛苦,那麼,用什麼方法來讀寫JSON資料才算好玩?有的,如果你耍過WCF,或許已經想到了——JSON序列化和還原序列化。
DataContractJsonSerializer類位於System.Runtime.Serialization.Json命名空間,我們只需要簡單的調用兩個方法就可以完成序列化和還原序列化。
WriteObject:序列化,把對象寫入JSON資料;
ReadObject:還原序列化,從JSON資料中讀入對象資料。
要完成今天的執行個體,我們先要定義一個類作為測試,這裡我就舉一個簡單的,員工類,它有三個屬性:姓名,聯絡電話,簡介。定義如下。
public class Employee { /// <summary> /// 員工姓名 /// </summary> public string Name { get; set; } /// <summary> /// 聯絡手機 /// </summary> public string Phone { get; set; } /// <summary> /// 簡介 /// </summary> public string Description { get; set; } }
對於UI,可以參考下面的XAML,我就不詳細說,你會看得懂的。
<Page x:Class="App1.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:App1" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}"> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition/> </Grid.ColumnDefinitions> <StackPanel Orientation="Vertical" Grid.Column="0" Margin="17"> <TextBlock Text="員工姓名:"/> <TextBox x:Name="txtName" Margin="0,2,0,14"/> <TextBlock Text="聯絡電話:"/> <TextBox x:Name="txtPhone" Margin="0,2,0,15"/> <TextBlock Text="員工簡介:"/> <TextBox x:Name="txtDesc" Margin="0,2,0,26"/> <Button Content="儲存資料" Click="onSave"/> </StackPanel> <StackPanel Orientation="Vertical" Grid.Column="1" Margin="15"> <Button Content="載入資料" Click="onLoadData"/> <TextBlock x:Name="tbInfo" TextWrapping="Wrap" Margin="0,15,0,0"/> </StackPanel> </Grid></Page>
切換到程式碼檢視,參考下面代碼:
using System;using System.Collections.Generic;using System.IO;using System.Linq;using Windows.Foundation;using Windows.Foundation.Collections;using Windows.UI.Xaml;using Windows.UI.Xaml.Controls;using Windows.UI.Xaml.Controls.Primitives;using Windows.UI.Xaml.Data;using Windows.UI.Xaml.Input;using Windows.UI.Xaml.Media;using Windows.UI.Xaml.Navigation;// 引入以下命名空間using System.Runtime.Serialization.Json;using Windows.Storage;using Windows.Storage.Pickers;using Windows.Storage.Streams;using Windows.UI.Popups;namespace App1{ public sealed partial class MainPage : Page { public MainPage() { this.InitializeComponent(); } private async void onLoadData(object sender, RoutedEventArgs e) { FileOpenPicker picker = new FileOpenPicker(); picker.CommitButtonText = "開啟"; picker.FileTypeFilter.Add(".json"); picker.SuggestedStartLocation = PickerLocationId.Desktop; StorageFile dataFile = await picker.PickSingleFileAsync(); if (dataFile != null) { // 開始讀取檔案 using (var stream = await dataFile.OpenSequentialReadAsync()) { // 還原序列化 DataContractJsonSerializer sz = new DataContractJsonSerializer(typeof(Employee)); Employee emp = (Employee)sz.ReadObject(stream.AsStreamForRead()); this.tbInfo.Text = string.Format("員工姓名:{0}\n聯絡電話:{1}\n簡介:{2}", emp.Name, emp.Phone, emp.Description); } } } private async void onSave(object sender, RoutedEventArgs e) { if (string.IsNullOrWhiteSpace(this.txtName.Text) || string.IsNullOrWhiteSpace(this.txtPhone.Text) || string.IsNullOrWhiteSpace(this.txtDesc.Text)) return; // 選擇檔案儲存位置 FileSavePicker picker = new FileSavePicker(); picker.CommitButtonText = "儲存"; picker.SuggestedStartLocation = PickerLocationId.Desktop; picker.FileTypeChoices.Add("JSON資料檔案", new string[] { ".json" }); StorageFile data = await picker.PickSaveFileAsync(); if (data != null) { using (var stream = await data.OpenAsync(FileAccessMode.ReadWrite)) { // 建立新對象 Employee emp = new Employee { Name = this.txtName.Text, Phone = this.txtPhone.Text, Description = this.txtDesc.Text }; // 開始序列化 DataContractJsonSerializer srz = new DataContractJsonSerializer(emp.GetType()); srz.WriteObject(stream.AsStreamForWrite(), emp); } this.ShowMessageBox("儲存成功。"); } } private async void ShowMessageBox(string msg) { MessageDialog dialog = new MessageDialog(msg); await dialog.ShowAsync(); } } public class Employee { /// <summary> /// 員工姓名 /// </summary> public string Name { get; set; } /// <summary> /// 聯絡手機 /// </summary> public string Phone { get; set; } /// <summary> /// 簡介 /// </summary> public string Description { get; set; } }}
就是這麼簡單,按下F5運行。在頁面左邊輸入相應內容,儲存。
用記事本開啟剛才儲存的檔案,你會看到以下內容:
回到應用程式,在頁面右邊,載入剛才儲存的JSON,如所示:
到此為止,基本上完成了JSON序列化和反序列的工作了,但是,還有一個問題,我們繼續討論一下,剛才我們用記事本查看儲存的JSON資料已經看到,JSON對象的欄位名和類的屬性名稱是一樣的,那麼,有些時候,我們並不希望這樣。如:在類中姓名的屬性名稱是Name,但在JSON資料中我希望它是emp_name。可以實現嗎?答案是肯定的。
這時候,我們只需把Employee類的定義改一下就可以了。
[System.Runtime.Serialization.DataContract] public class Employee { /// <summary> /// 員工姓名 /// </summary> [System.Runtime.Serialization.DataMember(Name = "emp_name")] public string Name { get; set; } /// <summary> /// 聯絡手機 /// </summary> [System.Runtime.Serialization.DataMember(Name = "emp_phoneno")] public string Phone { get; set; } /// <summary> /// 簡介 /// </summary> [System.Runtime.Serialization.DataMember(Name = "emp_desc")] public string Description { get; set; } }
如此一來,所儲存的JSON資料就如所示: