序列化、反序列化XML和JSON對象常用的方式


序列化、反序列化對象常用的兩種方式

序列化和反序列化對象常用的兩種方式

序列化是使用指定的格式將一個或多個對象轉換為字節序列的過程。反序列化則是相反的過程。

我們這里記錄2個常用的序列化和反序列化方法。

1、序列化為XML

2、系列化為JSON

一、序列化和反序列化XML

1.1、序列化XML

創建一個WPF程序。

新建一個類文件命名為Person,同時我們引用以下名稱空間,創建Person的類中的屬性,

使用[XmlAtribute("fname")]屬性,會把按當前類屬性從子節點變為當前節點的屬性,文件大小就變小了。可以嘗試一下去掉和不去掉之后產生的XML是否一樣。

using System;                        //DateTime
using System.Collections.Generic;    //List<T>,HashSet<T>
using System.Xml.Serialization;      //XmlSerializer

namespace SerializationAndDeserialization
{
    public class Person
    {
        public Person()
        {

        }
        public Person(decimal initialSalary)
        {
            Salary = initialSalary;
        }
        [XmlAttribute("fname")]
        public string FirstName { get; set; }
        [XmlAttribute("lname")]
        public string LastName { get; set; }
        [XmlAttribute("dob")]
        public DateTime DateOfBirth { get; set; }
        public HashSet<Person> Children { get; set; }
        protected decimal Salary { get; set; } 
    }
}

在MainWindow.cs文件中我們在構造函數中實例化Person。序列化到文件中,然后再反序列化回來。同時我們觀察使用XmlAttribute和不使用XmlAttribute有什么差別、觀察屬性定義為public類型和protected類型再序列化和反序列化過程中有什么不同。

using System;
using System.Collections.Generic; 
using System.Xml.Serialization;
using System.IO;
using System.Windows;
using static System.Console;
using static System.Environment;
using static System.IO.Path;

namespace SerializationAndDeserialization
{
    /// <summary>
    /// MainWindow.xaml 的交互邏輯
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            var people = new List<Person>()
            {
                new Person(30000M){ FirstName="Alice",LastName="Smith",DateOfBirth=new DateTime(1974,3,14)},
                new Person(40000M){ FirstName="Bob",LastName="Jone",DateOfBirth=new DateTime(1969,11,23)},
                new Person(20000M){ FirstName="Charlie",LastName="Cox",DateOfBirth=new DateTime(1984,5,4),Children=new HashSet<Person>{ new Person(0M)
                { FirstName="Sally",LastName="Cox",DateOfBirth=new DateTime(2000,7,12)} } }
            };
            var xs = new XmlSerializer(typeof(List<Person>));
            string path = Combine(CurrentDirectory, "pepple.xaml");
            using (FileStream stream = File.Create(path))
            {
                xs.Serialize(stream, people);
            }
            WriteLine("Witeten {0:N0} bytes of XML to {1}", arg0: new FileInfo(path).Length, arg1: path);
            WriteLine();
            WriteLine(File.ReadAllText(path));
            //系列化文件中不包含Salary,因為是Protected類型。
            //引用System.Xml.Serialization后使用[XmlAtribute("fname")]添加特性。文件結構就改變了,同時文件變小了。
        }
    }  
}

左邊是不使用再類屬性上添加 [XmlAttribute("")]的方法生成的xml文件。右側是使用 [XmlAttribute("")]屬性。右側文件小了很多。

1.2、反序列化XML

我們現在反序列化這個XML文件。

我們添加代碼后完整代碼如下:

using System;
using System.Collections.Generic;
using System.Xml.Serialization;
using System.IO;
using System.Windows;
using static System.Console;
using static System.Environment;
using static System.IO.Path;

namespace SerializationAndDeserialization
{
    /// <summary>
    /// MainWindow.xaml 的交互邏輯
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            var people = new List<Person>()
            {
                new Person(30000M){ FirstName="Alice",LastName="Smith",DateOfBirth=new DateTime(1974,3,14)},
                new Person(40000M){ FirstName="Bob",LastName="Jone",DateOfBirth=new DateTime(1969,11,23)},
                new Person(20000M){ FirstName="Charlie",LastName="Cox",DateOfBirth=new DateTime(1984,5,4),Children=new HashSet<Person>{ new Person(0M)
                { FirstName="Sally",LastName="Cox",DateOfBirth=new DateTime(2000,7,12)} } }
            };
            var xs = new XmlSerializer(typeof(List<Person>));
            string path = Combine(CurrentDirectory, "pepple.xaml");
            using (FileStream stream = File.Create(path))
            {
                xs.Serialize(stream, people);
            }
            WriteLine("Witeten {0:N0} bytes of XML to {1}", arg0: new FileInfo(path).Length, arg1: path);
            WriteLine();
            WriteLine(File.ReadAllText(path));
            //系列化文件中不包含Salary,因為是Protected類型。
            //引用System.Xml.Serialization后使用[XmlAtribute("fname")]添加特性。文件結構就改變了,同時文件變小了。

            //反序列化
            using (FileStream xmlLoad = File.Open(path, FileMode.Open))
            {
                var loadedPeople = (List<Person>)xs.Deserialize(xmlLoad); 
                foreach (var item in loadedPeople)
                {
                    WriteLine($"{item.LastName} has {item.Children.Count} children.");
                }
            }

        }
    }
}

點擊運行,我們觀察VS的輸出中這三行Log。我們的反序列化就完成了。

Smith has 0 children.
Jone has 0 children.
Cox has 1 children.

二、序列化和反序列化JSON

使用JSON序列化格式的最流行的.NET庫之一是Newtonsoft.Json,又名Json.NET。

我們再項目右鍵點擊彈出菜單中選擇管理NuGet包,點擊瀏覽輸入Newtonsoft.Json。選中找到的Newtonsoft.Json,點擊安裝。

2.1、嘗試序列化信息為JSON,並存放到文本文件中。

我們再后面添加如下代碼

using System;
using System.Collections.Generic;
using System.Xml.Serialization;
using System.IO;
using System.Windows;
using static System.Console;
using static System.Environment;
using static System.IO.Path;

namespace SerializationAndDeserialization
{
    /// <summary>
    /// MainWindow.xaml 的交互邏輯
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            var people = new List<Person>()
            {
                new Person(30000M){ FirstName="Alice",LastName="Smith",DateOfBirth=new DateTime(1974,3,14)},
                new Person(40000M){ FirstName="Bob",LastName="Jone",DateOfBirth=new DateTime(1969,11,23)},
                new Person(20000M){ FirstName="Charlie",LastName="Cox",DateOfBirth=new DateTime(1984,5,4),Children=new HashSet<Person>{ new Person(0M)
                { FirstName="Sally",LastName="Cox",DateOfBirth=new DateTime(2000,7,12)} } }
            };
            var xs = new XmlSerializer(typeof(List<Person>));
            string path = Combine(CurrentDirectory, "pepple.xaml");
            using (FileStream stream = File.Create(path))
            {
                xs.Serialize(stream, people);
            }
            WriteLine("Witeten {0:N0} bytes of XML to {1}", arg0: new FileInfo(path).Length, arg1: path);
            WriteLine();
            WriteLine(File.ReadAllText(path));
            //系列化文件中不包含Salary,因為是Protected類型。
            //引用System.Xml.Serialization后使用[XmlAtribute("fname")]添加特性。文件結構就改變了,同時文件變小了。

            //反序列化
            using (FileStream xmlLoad = File.Open(path, FileMode.Open))
            {
                var loadedPeople = (List<Person>)xs.Deserialize(xmlLoad);
                foreach (var item in loadedPeople)
                {
                    WriteLine($"{item.LastName} has {item.Children.Count} children.");
                }
            } 

            //序列化JSON
            string jsonPath = Combine(CurrentDirectory, "prople.json");
            using (StreamWriter jsonStream = File.CreateText(jsonPath))
            {
                var jss = new Newtonsoft.Json.JsonSerializer();
                jss.Serialize(jsonStream, people);
            }
            WriteLine();
            WriteLine($"Written {new FileInfo(jsonPath).Length} bytes of JSON to :{jsonPath}");
            WriteLine(File.ReadAllText(jsonPath));

        }
    }
}

調試運行輸出找到Log關鍵行如下。

Written 365 bytes of JSON to :E:\C#Notes\WPF\技巧\SerializationAndDeserialization\SerializationAndDeserialization\bin\Debug\prople.json
[{"FirstName":"Alice","LastName":"Smith","DateOfBirth":"1974-03-14T00:00:00","Children":null},{"FirstName":"Bob","LastName":"Jone","DateOfBirth":"1969-11-23T00:00:00","Children":null},{"FirstName":"Charlie","LastName":"Cox","DateOfBirth":"1984-05-04T00:00:00","Children":[{"FirstName":"Sally","LastName":"Cox","DateOfBirth":"2000-07-12T00:00:00","Children":null}]}]

2.2反序列化JSON文件為對象

反序列化的過程,我們使用File讀取文件內容,然后使用JsonConvert.DeserializeObject 來反序列化到對象。具體代碼如下:

using System;
using System.Collections.Generic;
using System.Xml.Serialization;
using System.IO;
using System.Windows;
using static System.Console;
using static System.Environment;
using static System.IO.Path;
using Newtonsoft.Json;
using System.Runtime.Serialization.Formatters.Binary;
using System.Diagnostics;

namespace SerializationAndDeserialization
{
    /// <summary>
    /// MainWindow.xaml 的交互邏輯
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            var people = new List<Person>()
            {
                new Person(30000M){ FirstName="Alice",LastName="Smith",DateOfBirth=new DateTime(1974,3,14)},
                new Person(40000M){ FirstName="Bob",LastName="Jone",DateOfBirth=new DateTime(1969,11,23)},
                new Person(20000M){ FirstName="Charlie",LastName="Cox",DateOfBirth=new DateTime(1984,5,4),Children=new HashSet<Person>{ new Person(0M)
                { FirstName="Sally",LastName="Cox",DateOfBirth=new DateTime(2000,7,12)} } }
            };
            //序列化XML
            var xs = new XmlSerializer(typeof(List<Person>));
            string path = Combine(CurrentDirectory, "pepple.xaml");
            using (FileStream stream = File.Create(path))
            {
                xs.Serialize(stream, people);
            }
            WriteLine("Witeten {0:N0} bytes of XML to {1}", arg0: new FileInfo(path).Length, arg1: path);
            WriteLine();
            WriteLine(File.ReadAllText(path));
            //系列化文件中不包含Salary,因為是Protected類型。
            //引用System.Xml.Serialization后使用[XmlAtribute("fname")]添加特性。文件結構就改變了,同時文件變小了。

            //反序列化XML
            using (FileStream xmlLoad = File.Open(path, FileMode.Open))
            {
                var loadedPeople = (List<Person>)xs.Deserialize(xmlLoad);
                foreach (var item in loadedPeople)
                {
                    WriteLine($"{item.LastName} has {item.Children.Count} children.");
                }
            }

            //序列化JSON
            string jsonPath = Combine(CurrentDirectory, "prople.json");
            using (StreamWriter jsonStream = File.CreateText(jsonPath))
            {
                var jss = new Newtonsoft.Json.JsonSerializer();
                jss.Serialize(jsonStream, people);
            }
            WriteLine();
            WriteLine($"Written {new FileInfo(jsonPath).Length} bytes of JSON to :{jsonPath}");
            //反序列化JSON
            var jsonStr = File.ReadAllText(jsonPath);
            WriteLine(File.ReadAllText(jsonPath));
            var persons = JsonConvert.DeserializeObject<List<Person>>(jsonStr);
            foreach (var item in persons)
            {
                Debug.WriteLine(item.ToString());
            }
        }
    }
}

再Person中重寫ToString()方法用於再反序列化結束后打印輸出內容。

using System;                        //DateTime
using System.Collections.Generic;    //List<T>,HashSet<T>
using System.Xml.Serialization;      //XmlSerializer

namespace SerializationAndDeserialization
{
    public class Person
    {
        public Person()
        {

        }
        public Person(decimal initialSalary)
        {
            Salary = initialSalary;
        }
        [XmlAttribute("fname")]
        public string FirstName { get; set; }
        [XmlAttribute("lname")]
        public string LastName { get; set; }
        [XmlAttribute("dob")]
        public DateTime DateOfBirth { get; set; }
        public HashSet<Person> Children { get; set; }
        protected decimal Salary { get; set; }
        public override string ToString()
        {
            return $"FirstName:{FirstName},LastName:{LastName},DateOfBirth:{DateOfBirth}";
        }
    }
}

整體代碼如上,序列化xml和反序列化xml,序列化json和反序列化json都再上面。適用於NET Core之前的版本。Net Core之后的有System.Text.Json對象。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM