序列化是什么?常见的序列化方式有哪些?什么时候我们会用到序列化?

devtools/2025/2/27 14:19:28/

序列化(Serialization)是指将对象的状态信息转换为可以存储或传输的形式(如字节序列、XML 文档、JSON 字符串等)的过程。反序列化则是序列化的逆过程,它将存储或接收到的字节序列、XML 文档、JSON 字符串等转换回对象的状态信息。通过序列化,对象可以在不同的环境中进行持久化存储或网络传输,而反序列化则可以让接收方恢复出原始的对象。

目录

常见的序列化方式

1. JSON 序列化

数据类型支持(JsonUtility不支持循环引用)

LitJson

使用场景

1. 数据存储

2. 网络通信

3. 配置文件

2.XML 序列化

3. 二进制序列化


常见的序列化方式

1. JSON 序列化

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,具有良好的可读性和跨语言性。它以键值对的形式组织数据,易于人类阅读和编写,也易于机器解析和生成。

Unity 内置了 JsonUtility 类用于简单的 JSON 序列化和反序列化,但功能相对有限。可以使用litJson.(LitJson 功能强大但使用相对复杂,适合处理复杂的数据结构和有特殊需求的场景;而 Unity 内置的 JsonUtility 简单易用,性能较好,适合处理简单的数据结构。与 Unity 内置的 JsonUtility 相比,LitJson 在使用时通常不需要为类添加序列化特性

数据类型支持(JsonUtility不支持循环引用)
  • 基本数据类型JsonUtility 能很好地处理基本数据类型(如果对象之间存在循环引用,JsonUtility 会抛出异常),如 intfloatstring 等。
  • 自定义类和结构体:对于自定义类和结构体,类或结构体必须是公共的,且成员变量也必须是公共的,JsonUtility 才能正确序列化和反序列化。
  • 集合类型:可以处理数组和 List<T> 等集合类型,但嵌套集合需要注意结构的正确性。
LitJson
  • 强大的类型支持:能处理各种复杂的数据类型,包括嵌套对象、数组、字典等,并且对于自定义类和结构体的处理较为灵活,支持手动实现序列化和反序列化逻辑。
  • 自定义序列化:允许开发者自定义序列化和反序列化过程,可通过实现自定义的转换器来满足特殊需求,例如对日期格式的自定义处理。
  • 处理循环引用:具备一定的处理对象循环引用的能力,虽然可能需要额外的配置,但能应对复杂对象关系的序列化场景。
使用场景
1. 数据存储

游戏中的配置数据、玩家进度等存储为 JSON 文件(实现数据持久化),方便后续读取和修改。

2. 网络通信

在网络通信中(在 Unity C# 的网络通信中,Newtonsoft.Json(Json.NET)是使用次数相对较多的序列化方案),将数据序列化为 JSON 格式进行传输,接收方再进行反序列化。

3. 配置文件

使用 JSON 文件作为游戏的配置文件,方便开发人员修改和管理。

由于使用这部分的功能在游戏开发过程之中可能是经常需要的,所以我们可以把Json的序列化和反序列化制作成Json模块的序列化反序列化功能框架。核心功能代码示例如下:

        private static readonly JsonType JsonTypes = JsonType.LitJson;public static void SaveData(object data, string fileName){string path = UnityEngine.Application.persistentDataPath + "/" + fileName + ".json";string jsonStr = "";switch (JsonTypes){case JsonType.JsonUtlity:jsonStr = JsonUtility.ToJson(data);break;case JsonType.LitJson:jsonStr = JsonMapper.ToJson(data);break;}File.WriteAllText(path,jsonStr);}public static T LoadData<T>(string fileName) where T : new(){string path = UnityEngine.Application.streamingAssetsPath + "/" + fileName + ".json";if (!File.Exists(path)) path = UnityEngine.Application.persistentDataPath + "/" + fileName + ".json";if (!File.Exists(path)) return new T();string jsonStr = File.ReadAllText(path);T data = default(T);switch (JsonTypes){case JsonType.JsonUtlity:data = JsonUtility.FromJson<T>(jsonStr);break;case JsonType.LitJson:data = JsonMapper.ToObject<T>(jsonStr);break;}return data;}

2.XML 序列化

XML(eXtensible Markup Language)是一种标记语言,用于存储和传输数据。它具有良好的结构化和扩展性,支持复杂的数据结构和元数据。

xml序列化的使用场景与json的使用场景相似,都是一种数据持久化的序列化方案,我们还可以使用xml制作配置文件书写一些编辑器小工具的功能。例如生成消息类等。

  • 若要使用 System.Xml.Serialization.XmlSerializer 对自定义类进行序列化和反序列化,类必须是可序列化的。这意味着类及其所有公共字段都必须是可访问的,并且类要有无参构造函数。如果类包含私有字段,默认情况下这些字段不会被序列化,除非使用特性(如 [XmlElement])进行标记。
  • 可以使用 XML 相关的特性(如 [XmlRoot][XmlElement][XmlAttribute] 等)来控制 XML 元素和属性的生成。例如,[XmlRoot] 可以指定 XML 根元素的名称,[XmlElement] 可以指定 XML 元素的名称,[XmlAttribute] 可以将字段序列化为 XML 属性。
  • XML 文件的格式必须严格遵循 XML 规范,否则在解析时会抛出异常。在读取和解析 XML 文件时,要进行异常处理,以确保程序的健壮性。
  • 不同平台可能对文件编码有不同的默认设置,在保存和读取 XML 文件时,要明确指定编码格式,以确保数据的正确传输和解析。通常建议使用 UTF - 8 编码。

使用xml制作编辑器小工具的简单案例:自动生成脚本。(展示一部分)

        public void GenerateEnum(XmlNodeList list){string namespaceStr = "";string enumNameStr = "";string fieldStr = "";foreach (XmlNode enumNode in list){//获取命名空间配置信息namespaceStr = enumNode.Attributes?["namespace"].Value;//获取枚举名配置信息enumNameStr = enumNode.Attributes?["name"].Value;XmlNodeList enumFields = enumNode.SelectNodes("field");//一个新的枚举需要清空上一次拼接的字段字符串fieldStr = "";if (enumFields == null){Debug.Log("不存在field字段,请检查您的xml配置文件是否准确!");return;}foreach (XmlNode enumField in enumFields){fieldStr += "\t\t" + enumField.Attributes?["name"].Value;if (enumField.InnerText != "")fieldStr += "=" + enumField.InnerText;fieldStr += ",\r\n";}//对所有可变的内容进行拼接string enumStr = $"namespace {namespaceStr}\r\n" +"{\r\n" +$"\tpublic enum {enumNameStr}\r\n" +"\t{\r\n" +$"{fieldStr}" +"\t}\r\n" +"}";//保存文件的路径string path = _saveDataPath + namespaceStr + "/Enum/";if (!Directory.Exists(path))Directory.CreateDirectory(path);File.WriteAllText(path+enumNameStr+".cs",enumStr);}Debug.Log("枚举生成结束");}
        private static readonly GenerateCSharp generateCSharp = new();private static readonly string protoInfoPath = Application.dataPath + "/Scripts/Game/Editor/XmlTool/Net.xml";[MenuItem("ProtocolTool/生成C#脚本")]private static void GenerateCSharp(){//根据这些信息 拼接字符串 生成对应的脚本//生成对应枚举脚本generateCSharp.GenerateEnum(GetNodes("enum"));//生成对应的数据结构类脚本generateCSharp.GenerateData(GetNodes("data"));//生成对应消息类脚本generateCSharp.GenerateMsg(GetNodes("message"));//刷新编辑器界面AssetDatabase.Refresh();}

3. 二进制序列化

二进制序列化将对象转换为字节序列,这种方式通常比文本格式(如 JSON、XML)更紧凑,读写速度更快,但可读性较差。不同的编程语言有不同的二进制序列化机制。(常用于需要高效存储和传输大量数据的场景,如游戏开发、数据库系统等。

代码示例:

        /// <summary>/// 在游戏过程中存储的数据/// </summary>/// <param name="obj">读取类型</param>/// <param name="isNetworkTransmission">是否使用网络运输</param>/// <param name="isEncrypt">是否需要加密数据</param>/// <typeparam name="T"></typeparam>public void AutoCreatFile<T>(T obj,bool isNetworkTransmission=false,bool isEncrypt=true) where T:class{_key = (byte)UnityEngine.Random.Range(1f, 200f);string fileName = typeof(T).Name;if (!Directory.Exists(Application.dataPath + "/BinaryAutoScripts"))_rootFile = Directory.CreateDirectory(Application.dataPath + "/BinaryAutoScripts");if (!_passWordDic.ContainsKey(fileName) && isEncrypt)_passWordDic.Add(fileName,_key);else_passWordDic[fileName] = _key;BinaryFormatter bf = new BinaryFormatter();if (isNetworkTransmission){using var ms = new MemoryStream();bf.Serialize(ms, obj);byte[] bytes = ms.GetBuffer();if (isEncrypt)for (int i = 0; i < bytes.Length; i++)bytes[i] ^= _key;File.WriteAllBytes(Application.dataPath + $"/BinaryAutoScripts/{fileName}_Net.nicolepotter", bytes);}else{using var fs = new FileStream(Application.dataPath + $"/BinaryAutoScripts/{fileName}.nicolepotter", FileMode.OpenOrCreate, FileAccess.Write);bf.Serialize(fs, obj);fs.Flush();}
#if UNITY_EDITORAssetDatabase.Refresh();
#endif}

http://www.ppmy.cn/devtools/163087.html

相关文章

Python爬虫系统搭建教程,从0开始搭建爬虫系统(附安装包)

文章目录 前言一、Python环境搭建1.Python安装2.选择Python开发环境3. 安装必要库 二、基础爬虫构建1. 发送请求获取网页2. 解析网页提取数据 三、使用 Scrapy 框架搭建系统1. 创建 Scrapy 项目2. 生成爬虫3. 编写爬虫代码4. 运行爬虫 四、应对反爬虫机制1. 常见反爬虫手段2. 解…

FPGA开发要学些什么?如何快速入门?

随着FPGA行业的不断发展&#xff0c;政策的加持和投入的研发&#xff0c;近两年FPGA行业的薪资也是水涨船高&#xff0c;一些人转行后拿到了薪资30W&#xff0c;甚至有一些能力强的人可以拿到60W&#xff0c;看到这里想必不少人表示很心动&#xff0c;但又不知道怎么转&#xf…

jdk21下载、安装(Windows、Linux、macOS)

Windows 系统 1. 下载安装 访问 Oracle 官方 JDK 下载页面 或 OpenJDK 下载页面&#xff0c;根据自己的系统选择合适的 Windows 版本进行下载&#xff08;通常选择 .msi 安装包&#xff09;。 2. 配置环境变量 右键点击 “此电脑”&#xff0c;选择 “属性”。 在左侧导航栏…

【DeepSeek系列】05 DeepSeek核心算法改进点总结

文章目录 一、DeepSeek概要二、4个重要改进点2.1 多头潜在注意力2.2 混合专家模型MoE2.3 多Token预测3.4 GRPO强化学习策略 三、2个重要思考3.1 大规模强化学习3.2 蒸馏方法&#xff1a;小模型也可以很强大 一、DeepSeek概要 2024年&#xff5e;2025年初&#xff0c;DeepSeek …

详解直方图均衡化

直方图均衡化&#xff08;Histogram Equalization&#xff09; 是图像处理中一种常用的对比度增强技术&#xff0c;通过调整图像的灰度分布&#xff0c;使得图像的直方图尽可能均匀分布&#xff0c;从而提高图像的对比度和细节表现。以下是直方图均衡化的原理详解&#xff1a; …

【Maven】-- Maven Scope 详解

目录 Maven Scope 详解 1. 引言 2. Maven 依赖范围&#xff08;Scope&#xff09;分类 2.1 compile&#xff08;默认范围&#xff09; 2.2 provided 2.3 runtime 2.4 test 2.5 system 2.6 import&#xff08;仅用于 dependencyManagement&#xff09; 3. Scope 作用范…

系统架构设计:系统分析与设计需要掌握的基本理念

在软件工程中,系统分析与设计是构建高质量软件的关键步骤。它决定了软件系统的架构、功能、性能和可维护性。本文将详细介绍系统分析与设计的重要知识点,并结合相关代码示例,帮助你更好地理解和应用这些知识。 一、系统分析 系统分析是软件开发生命周期中的一个重要阶段,…

obj离线加载(vue+threejs)+apk方式浏览

demo需求&#xff1a;移动端&#xff0c;实现obj本地离线浏览 结合需求&#xff0c;利用&#xff08;vue2threejs173&#xff09;进行obj的加载&#xff0c;然后采用apk方式&#xff08;hbuilderX打包发布&#xff09;移动端浏览&#xff1b; https://github.com/bianbian886/…