二进制序列化器、XML序列化器、Json序列化器

简介: 序列化是将对象的状态信息转换未可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区读取或反序列化对象的状态,重新创建对象。

序列化是将对象的状态信息转换未可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区读取或反序列化对象的状态,重新创建对象。

序列化之前:对象

序列化之后:把对象转换成另一种形式存储

1、二进制序列化器

BinaryFormatter

保存成二进制数据流。

示例:

序列化:
public class Student
    {
        public Student(int id, string name, int age, string grade)
        {
            this.ID = id;
            this.Name = name;
            this.Age = age;
            this.Grade = grade;
        }
        public int ID { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
        public string Grade { get; set; }
    }
`
`
class Program
    {
        static void Main(string[] args)
        {
            List<Student> students = new List<Student>();
            for (int i = 1; i < 10; i++)
            {
                Student student = new Student(i, "学生" + i, 18 + i, "年级二");
                students.Add(student);
            }

            FileStream fileStream = new FileStream(@"E:\dotnet\SerilizeAndDeserialize\SerilizeAndDeserialize\data\student.dat", FileMode.OpenOrCreate);
            BinaryFormatter bFormat = new BinaryFormatter();
            bFormat.Serialize(fileStream, students);
            fileStream.Close();
            Console.WriteLine("序列化成功");
        }
    }
`

运行代码,此时会遇到如下图报错;

Student没有标记序列化。

解决方法
   [Serializable]
   //如果要想保存某个class中的字段,必须在class前面加个这样Attribute
    public class Student
    {
        public Student(int id, string name, int age, string grade)
        {
            this.ID = id;
            this.Name = name;
            this.Age = age;
            this.Grade = grade;
        }
        public int ID { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
        public string Grade { get; set; }
    }

之后可以看到成功序列化后,保存至student.dat文件中。

反序列化:
FileStream stream = new FileStream(@"E:\dotnet\SerilizeAndDeserialize\SerilizeAndDeserialize\data\student.dat", FileMode.Open);
            BinaryFormatter bdFormat = new BinaryFormatter();
            List<Student> students1 = (List<Student>)bFormat.Deserialize(stream);
            stream.Close();
Console.WriteLine("反序列化成功");
进一步地:

从 .NET 5.开始,以下 API 标记为已过时

详见:

SYSLIB0011:BinaryFormatter 序列化已过时

解决方法

请考虑使用 JsonSerializerXmlSerializer,而不是 BinaryFormatter

2、XML序列化器

XmlSerializer

保存成XML文件,但没有其他额外信息。另外需要注意的是,XmlSerializer只能保存public类型的字段,而其他两种类型能保存所有类型的字段。

序列化:

            Circle circle = new Circle
            {
                Radius = 10.1,
                BgColor = "Black"
            };
            XmlDocument xd = new XmlDocument();
            using (StringWriter sw = new StringWriter())
            {
                XmlSerializer xz = new XmlSerializer(circle.GetType());
                xz.Serialize(sw, circle);
                Console.WriteLine(sw.ToString());
                xd.LoadXml(sw.ToString());
                xd.Save(@"E:\C#\SerilizeAndDeserialize\SerilizeAndDeserialize\data\circle.xml");
            }

反序列化:

Circle circle2 = new Circle();
            using (XmlReader reader = XmlReader.Create(@"E:\C#\SerilizeAndDeserialize\SerilizeAndDeserialize\data\circle.xml"))
            {
                XmlSerializer xz = new XmlSerializer(circle2.GetType());
                circle2 = (Circle)xz.Deserialize(reader);
                Console.WriteLine(reader.ToString());
            }

三、JSON序列化器

Json序列化有很多种方法,这里我们介绍.Net 标准库 System.Text.JsonSystem.Runtime.Serialization.Json 和 Newtonsoft 库Newtonsoft.Json;

System.Text.Json
            Circle circle = new Circle
            {
                Radius = 10.1,
                BgColor = "Black"
            };
            string json = JsonSerializer.Serialize(circle); //序列化
            Circle circle2 = JsonSerializer.Deserialize<Circle>(json); //反序列化
Newtonsoft.Json
string json = JsonConvert.SerializeObject(circle); //序列化
Circle circle2 = JsonConvert.DeserializeObject<Circle>(json); //反序列化
System.Runtime.Serialization.Json
DataContractJsonSerializer dataContractJsonSerializer = new DataContractJsonSerializer(typeof(Circle));
            using (MemoryStream memoryStream = new MemoryStream())
            {
                dataContractJsonSerializer.WriteObject(memoryStream, circle);
            }
DataContractJsonSerializer dataContractJsonSerializer1 = new DataContractJsonSerializer(typeof(Circle));
            MemoryStream memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(jsonText));
            Circle result = (Circle)((object)dataContractJsonSerializer1.ReadObject(memoryStream));
Newtonsoft.Json.Linq中的JObject类型

以上例子都是使用强类型进行序列化和反序列操作,但有时也会用到不指定类型而直接操作Json格式数据的情况,此时就需要用位于命名空间ewtonsoft.Json.Linq中的JObject类型的对象:

string jsonStr = @"{""MyNum"": 10,""MyStr"": ""Hello World""}";
JObject jObject = JObject.Parse(jsonStr);
Console.WriteLine(jObject.ToString(Formatting.None)); //{"MyNum":10,"MyStr":"Hello World"}
//打印一条属性的值
Console.WriteLine(jObject["MyStr"].Value<string>()); //Hello World
//添加一条属性
jObject.Add("MyStr2", "HaHa");
//打印当前Json字符串
Console.WriteLine(jObject.ToString(Formatting.None)); //{"MyNum":10,"MyStr":"Hello World","MyStr2":"HaHa"}

四、自定义某个字段/属性的序列化/反序列化规则

当接收到的Json格式字符串与本地已有类型不统一时,需要进行自定义的反序列化过程,反之亦然,例如Json字符串中以字符串"TRUE"表示布尔类型true(不自定义,这个过程依然走的通,只是以此举例),以字符串"FALSE"表示布尔类型false时,需要自定义如下:

/// <summary>
/// 自定义布尔类型数据转换规则
/// </summary>
public class MyBoolConverter : JsonConverter{
  private const string TrueStr = "TRUE";
  private const string FalseStr = "FALSE";
  public override bool CanConvert(Type objectType) => true;

  //反序列化  
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)  {
    if (reader.ValueType == typeof(string))
    {
      if ((string)reader.Value == TrueStr)
      {
        return true;
      }
      else      {
        return false;
      }
    }
    return false;
  }

  //序列化  
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)  {
    if (value.GetType() == typeof(bool))
    {
      bool result = (bool)value;
      if (result)
      {
        writer.WriteValue(TrueStr);
      }
      else      {
        writer.WriteValue(FalseStr);
      }
    }
  }
}

然后,在需要操作的类型定义中的字段/属性中加入该特性:

private class MyClass{
  [JsonConverter(typeof(MyBoolConverter))]
  public bool MyBool;
}

此时

string jsonStr = @"{""MyBool"": ""TRUE""}";
MyClass1 myClass = JsonConvert.DeserializeObject<MyClass1>(jsonStr);
Console.WriteLine(myClass.MyBool); //True
Console.WriteLine(JsonConvert.SerializeObject(myClass)); //{"MyBool":"TRUE"}
相关文章
|
3月前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
236 1
|
3月前
|
JSON 网络协议 安全
【Java基础】(1)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
249 1
|
4月前
|
XML JSON 编解码
从JSON到Protobuf,深入序列化方案的选型与原理
序列化是数据跨边界传输的“翻译官”,将结构化数据转为二进制流。JSON可读性强但冗余大,Protobuf高效紧凑、性能优越,成主流选择。不同场景需权衡标准化与定制优化,选最合适方案。
375 3
|
6月前
|
JSON 人工智能 Go
在Golang中序列化JSON字符串的教程
在Golang中,使用`json.Marshal()`可将数据结构序列化为JSON格式。若直接对JSON字符串进行序列化,会因转义字符导致错误。解决方案包括使用`[]byte`或`json.RawMessage()`来避免双引号被转义,从而正确实现JSON的序列化与反序列化。
327 7
|
7月前
|
XML JSON Java
go语言之JSON序列化
本文介绍了Go语言中的JSON序列化与反序列化,其操作与Java类似。需要注意的是,由于Go语言的包管理机制,变量和引入包的首字母需大写,以便其他包引用。示例代码展示了如何将`Student`结构体进行JSON序列化(返回字节数组,需转为字符串)及反序列化。此外,文章还说明了通过tag(如`json`和`xml`)指定序列化变量的重要性,以避免因包间访问限制导致反序列化失败或值为null的问题。
147 0
|
8月前
|
JSON JavaScript 前端开发
Go语言JSON 序列化与反序列化 -《Go语言实战指南》
本文介绍了 Go 语言中使用 `encoding/json` 包实现 JSON 与数据结构之间的转换。内容涵盖序列化(`Marshal`)和反序列化(`Unmarshal`),包括基本示例、结构体字段标签的使用、控制字段行为的标签(如 `omitempty` 和 `-`)、处理 `map` 和切片、嵌套结构体序列化、反序列化未知结构(使用 `map[string]interface{}`)以及 JSON 数组的解析。最后通过表格总结了序列化与反序列化的方法及类型要求,帮助开发者快速掌握 JSON 数据处理技巧。
|
JSON JavaScript 前端开发
Go语言中json序列化的一个小坑,建议多留意一下
在Go语言开发中,JSON因其简洁和广泛的兼容性而常用于数据交换,但其在处理数字类型时存在精度问题。本文探讨了JSON序列化的一些局限性,并介绍了两种替代方案:Go特有的gob二进制协议,以及msgpack,两者都能有效解决类型保持和性能优化的问题。
439 7
|
7月前
|
存储 Java 编译器
说一说关于序列化/反序列化中的细节问题
我是小假 期待与你的下一次相遇 ~
139 1
|
7月前
|
JSON Java 数据库连接
|
8月前
|
存储 安全 IDE
说一说序列化与反序列化中存在的问题
本文详细解析了Java中的序列化机制,包括序列化的概念、实现方式及应用场景。通过Student类的实例演示了对象的序列化与反序列化过程,并分析了`Serializable`接口的作用以及`serialVersionUID`的重要意义。此外,文章还探讨了如何通过自定义`readObject()`方法增强序列化的安全性,以及解决可序列化单例模式中可能产生的多实例问题。最后提供了代码示例和运行结果,帮助读者深入理解序列化的原理与实践技巧。
215 2