当前位置: 首页 > news >正文

深入浅出:序列化与反序列化的全面解析

文章目录

        • 1. 引言
        • 2. 什么是序列化?
          • 2.1 为什么需要序列化?
        • 3. 什么是反序列化?
          • 3.1 反序列化的重要性
        • 4. 序列化与反序列化的实现
          • 4.1 JSON (JavaScript Object Notation)
          • 4.2 XML (eXtensible Markup Language)
          • 4.3 Protocol Buffers (Protobuf)
          • 4.4 MessagePack
        • 5. 安全性考虑
        • 6. 性能优化
        • 7. 结论
      • 附录:常见问题解答
        • Q1: 什么时候应该选择JSON而不是XML?
        • Q2: Protocol Buffers和MessagePack有什么区别?
        • Q3: 如何防止反序列化攻击?

1. 引言

在软件开发中,序列化(Serialization)反序列化(Deserialization) 是两个非常重要的概念。它们涉及到数据的转换、传输和存储。本文将通过通俗易懂的语言和实际代码示例,帮助读者理解这两个过程,并探讨如何在不同的编程语言和应用场景中实现它们。

2. 什么是序列化?

序列化是指将对象的状态信息转换为可以存储或传输的格式的过程。这个格式可以是字节流、JSON、XML等。通过序列化,我们可以将复杂的数据结构简化为一种线性的、易于处理的形式。

2.1 为什么需要序列化?
  • 数据传输:当应用程序需要通过网络发送对象时,必须先将其序列化为一种可以在网络上传输的格式。
  • 数据存储:为了保存对象状态到文件或数据库,我们需要将对象序列化。
  • 缓存:有时我们会将对象序列化后存储在内存或磁盘中作为缓存,以提高访问速度。
  • 版本控制:序列化后的数据可以更容易地进行版本管理,尤其是在分布式系统中。
3. 什么是反序列化?

反序列化是序列化的逆过程,即将序列化的数据还原为原始的对象。通过反序列化,我们可以从存储介质或网络接收的数据中重建对象。

3.1 反序列化的重要性
  • 数据恢复:从持久存储中读取对象并恢复其状态。
  • 网络接收:接收来自网络的序列化数据,并将其转换回可用的对象。
  • 跨平台兼容性:不同平台上的程序可以通过序列化和反序列化来共享对象。
4. 序列化与反序列化的实现

不同的编程语言提供了多种方式来实现序列化和反序列化。以下是一些常见的方法及其Java代码示例。

4.1 JSON (JavaScript Object Notation)

JSON是一种轻量级的数据交换格式,易于阅读和编写,同时也易于机器解析和生成。许多语言都有内置的库支持JSON序列化和反序列化。在Java中,常用的库有Jackson和Gson。

使用Jackson库

首先,添加Maven依赖:

<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.13.0</version>
</dependency>

然后,编写代码:

import com.fasterxml.jackson.databind.ObjectMapper;import java.io.IOException;public class JsonExample {public static void main(String[] args) throws IOException {// 定义一个Java对象Person person = new Person("Alice", 30, "Beijing");// 创建ObjectMapper实例ObjectMapper objectMapper = new ObjectMapper();// 序列化为JSON字符串String json = objectMapper.writeValueAsString(person);System.out.println("Serialized JSON: " + json);// 反序列化为Java对象Person deserializedPerson = objectMapper.readValue(json, Person.class);System.out.println("Deserialized JSON: " + deserializedPerson);}// 定义Person类static class Person {private String name;private int age;private String city;public Person() {}public Person(String name, int age, String city) {this.name = name;this.age = age;this.city = city;}@Overridepublic String toString() {return "Person{name='" + name + "', age=" + age + ", city='" + city + "'}";}}
}
4.2 XML (eXtensible Markup Language)

XML是一种更复杂的标记语言,适用于描述具有层次结构的数据。尽管它比JSON更冗长,但在某些领域(如配置文件)仍然广泛使用。在Java中,可以使用JAXB(Java Architecture for XML Binding)来进行XML的序列化和反序列化。

使用JAXB库

首先,添加Maven依赖:

<dependency><groupId>javax.xml.bind</groupId><artifactId>jaxb-api</artifactId><version>2.3.1</version>
</dependency>
<dependency><groupId>org.glassfish.jaxb</groupId><artifactId>jaxb-runtime</artifactId><version>2.3.1</version>
</dependency>

然后,编写代码:

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.StringReader;
import java.io.StringWriter;public class XmlExample {public static void main(String[] args) throws JAXBException {// 定义一个Java对象Person person = new Person("Alice", 30, "Beijing");// 创建JAXBContext实例JAXBContext context = JAXBContext.newInstance(Person.class);// 序列化为XML字符串Marshaller marshaller = context.createMarshaller();marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);StringWriter writer = new StringWriter();marshaller.marshal(person, writer);String xml = writer.toString();System.out.println("Serialized XML:\n" + xml);// 反序列化为Java对象Unmarshaller unmarshaller = context.createUnmarshaller();StringReader reader = new StringReader(xml);Person deserializedPerson = (Person) unmarshaller.unmarshal(reader);System.out.println("Deserialized XML: " + deserializedPerson);}// 定义Person类,并添加JAXB注解import javax.xml.bind.annotation.XmlRootElement;@XmlRootElementstatic class Person {private String name;private int age;private String city;public Person() {}public Person(String name, int age, String city) {this.name = name;this.age = age;this.city = city;}@Overridepublic String toString() {return "Person{name='" + name + "', age=" + age + ", city='" + city + "'}";}// Getters and Setters (omitted for brevity)}
}
4.3 Protocol Buffers (Protobuf)

Protocol Buffers是由Google开发的一种语言中立、平台中立、可扩展的序列化数据格式。它通常用于网络通信和数据存储。

首先,定义一个.proto文件:

syntax = "proto3";message Person {string name = 1;int32 age = 2;string city = 3;
}

然后,使用protoc编译器生成Java代码:

protoc --java_out=. person.proto

最后,在Java中使用生成的代码进行序列化和反序列化:

import com.example.Person;import java.nio.file.Files;
import java.nio.file.Paths;public class ProtobufExample {public static void main(String[] args) throws Exception {// 创建一个Person对象Person person = Person.newBuilder().setName("Alice").setAge(30).setCity("Beijing").build();// 序列化为字节流byte[] serializedData = person.toByteArray();System.out.println("Serialized Protobuf: " + new String(serializedData));// 反序列化为Person对象Person deserializedPerson = Person.parseFrom(serializedData);System.out.println("Deserialized Protobuf: " + deserializedPerson);}
}
4.4 MessagePack

MessagePack是一种高效的二进制序列化格式,旨在提供紧凑的编码和快速的处理速度。它类似于JSON,但体积更小,性能更高。在Java中,可以使用Kryo库来进行MessagePack的序列化和反序列化。

使用Kryo库

首先,添加Maven依赖:

<dependency><groupId>com.esotericsoftware</groupId><artifactId>kryo</artifactId><version>5.0.0</version>
</dependency>

然后,编写代码:

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;public class MessagePackExample {public static void main(String[] args) {// 定义一个Java对象Person person = new Person("Alice", 30, "Beijing");// 创建Kryo实例Kryo kryo = new Kryo();kryo.register(Person.class);// 序列化为字节流ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();Output output = new Output(byteArrayOutputStream);kryo.writeClassAndObject(output, person);output.close();byte[] packedData = byteArrayOutputStream.toByteArray();System.out.println("Serialized MessagePack: " + Arrays.toString(packedData));// 反序列化为Java对象ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(packedData);Input input = new Input(byteArrayInputStream);Person unpackedPerson = (Person) kryo.readClassAndObject(input);input.close();System.out.println("Deserialized MessagePack: " + unpackedPerson);}// 定义Person类static class Person {private String name;private int age;private String city;public Person() {}public Person(String name, int age, String city) {this.name = name;this.age = age;this.city = city;}@Overridepublic String toString() {return "Person{name='" + name + "', age=" + age + ", city='" + city + "'}";}}
}
5. 安全性考虑

在进行反序列化时,我们必须特别注意安全性问题。恶意用户可能会构造特制的序列化数据,导致程序执行任意代码或造成其他安全漏洞。因此,在反序列化过程中,应该:

  • 验证数据来源:确保只对可信来源的数据进行反序列化。
  • 限制反序列化的内容:避免反序列化不受信任的类或类型。
  • 使用安全的序列化格式:例如,JSON通常被认为比XML更安全,因为它不支持外部实体引用。
6. 性能优化

对于大规模的数据集或高并发的应用场景,序列化和反序列化的性能至关重要。为了提高效率,可以采取以下措施:

  • 选择合适的序列化格式:根据应用场景选择最合适的格式,如JSON、MessagePack或Protocol Buffers。
  • 批量处理:尽量减少序列化和反序列化的次数,采用批量处理的方式。
  • 压缩数据:在传输或存储之前对序列化数据进行压缩,以减少带宽占用和存储空间。
7. 结论

序列化和反序列化是构建高效、可靠的软件系统不可或缺的技术。通过理解它们的工作原理和最佳实践,我们可以更好地应对数据交换和持久化的挑战。无论你是新手还是经验丰富的开发者,掌握这些技能都将为你带来巨大的优势。


附录:常见问题解答

Q1: 什么时候应该选择JSON而不是XML?

A1: JSON通常更适合简单的数据结构和轻量级的应用场景,因为它更简洁、易于阅读和解析。而XML则更适合复杂的、层次结构明显的数据,或者需要严格的模式验证的场景。

Q2: Protocol Buffers和MessagePack有什么区别?

A2: Protocol Buffers由Google开发,支持强类型和严格的消息定义,适合大型项目和跨平台通信。MessagePack则更加灵活,体积更小,性能更高,适合对性能要求较高的场景。

Q3: 如何防止反序列化攻击?

A3: 为了防止反序列化攻击,建议使用安全的序列化格式(如JSON),并严格限制反序列化的内容。此外,还可以通过白名单机制,只允许特定的类或类型进行反序列化。


希望这篇文档能够帮助你了解序列化和反序列化。如果有任何问题,请随时提问!欢迎在评论区交流讨论

相关文章:

深入浅出:序列化与反序列化的全面解析

文章目录 1. 引言2. 什么是序列化&#xff1f;2.1 为什么需要序列化&#xff1f; 3. 什么是反序列化&#xff1f;3.1 反序列化的重要性 4. 序列化与反序列化的实现4.1 JSON (JavaScript Object Notation)4.2 XML (eXtensible Markup Language)4.3 Protocol Buffers (Protobuf)4…...

word实践:正文/标题/表图等的共用模板样式设置

说在前面 最近使用word新建文件很多&#xff0c;发现要给大毛病&#xff0c;每次新建一个word文件&#xff0c;标题/正文的字体、大小和间距都要重新设置一遍&#xff0c;而且每次设置这些样式都忘记了参数&#xff0c;今天记录一下&#xff0c;以便后续方便查看使用。现在就以…...

Blender中使用BlenderGIS插件快速生成城市建筑模型

导入下载 BlenderGIS 插件 去github上下载其压缩包&#xff0c;地址如下&#xff1a; https://github.com/domlysz/BlenderGIS 在BlenderGIS中导入这个插件压缩包&#xff1a; 点击上方菜单栏的编辑&#xff0c;点击偏好设置 在插件>从磁盘安装中导入刚刚下载的压缩包 可…...

【单元测试】单元测试的重要性

1一些错误的认识 在实际的单元测试过程中总会有一些错误的认识左右着我们&#xff0c;使之成为单元测试最大的障碍&#xff0c;在此将其一一分析如下&#xff1a; 它太浪费时间了&#xff0c;现在要赶进度&#xff0c;时间上根本不允许&#xff0c;或者随便做做应付领导。 …...

Codeforces Round 992 (Div. 2)

这场cf只在b卡了一下&#xff0c;因为b真是犯蠢了&#xff0c;我以为会向下取整&#xff0c;结果是完全就不取整&#xff0c;或者说是向上取整&#xff0c;卡了我半个小时&#xff0c;要不是紧急看了题一下&#xff0c;昨天那场就毁了 话不多说&#xff0c;直接开讲 A. Game …...

el-table一键选择全部行,切换分页后无法勾选

el-table一键全选&#xff0c;分页的完美支持 问题背景尝试解决存在问题问题分析 解决方案改进思路如下具体代码实现如下 问题背景 现在有个需求&#xff0c;一个表格有若干条数据(假设数量大于20&#xff0c;每页10条&#xff0c;保证有2个以上分页即可)。 现在需要在表格上方…...

负载均衡最佳实践及自定义负载均衡器

文章目录 负载均衡最佳实践及自定义负载均衡器一、负载均衡概述二、轮询负载均衡器&#xff08;一&#xff09;理论介绍&#xff08;二&#xff09;Java 实现示例&#xff08;三&#xff09;关键步骤&#xff08;四&#xff09;流程图 三、随机负载均衡器&#xff08;一&#x…...

大模型 LMDeploy 量化部署

1 模型部署 定义&#xff1a; 在软件工程中&#xff0c;部署通常指的是将开发完毕的软件投入使用的过程。在人工智能领域&#xff0c;模型部署是实现深度学习算法落地应用的关键步骤。简单来说&#xff0c;模型部署就是将训练好的深度学习模型在特定环境中运行的过程。 场景…...

算法设计5_分支限界法

分支限界法 分支限界法常以广度优先或以最小耗费(最大效益)优先的方式搜索问题的解空间树&#xff0c;裁剪那些不能得到最优解的子树以提高搜索效率。 步骤&#xff1a; ① 定义解空间(对解编码); ② 确定解空间的树结构&#xff1b; ③ 按BFS等方式搜索&#xff1a; a.每个活…...

2025年人工智能专业可以考哪些证书呢?

人工智能是目前全球热门的专业领域之一&#xff0c;随着人工智能应用范围的不断扩大&#xff0c;越来越多的人开始关注人工智能相关证书的获取。那么&#xff0c;人工智能专业可以考什么证书呢&#xff1f;本文将为大家介绍人工智能相关证书的种类。 人工智能机器视觉应用工程师…...

仿真技术助力高尔夫球打破传统设计局限,实现球杆强大的功能

Altair近日宣布与业内领先的高尔夫装备制造商 Cleveland Golf 开展合作&#xff0c;以设计新款 HiBore XL 球杆。借助 Altair 先进的仿真与设计技术&#xff0c;Cleveland Golf 不断刷新高尔夫装备的行业标准&#xff0c;并在球杆产品设计方面实现突破。 Cleveland Golf 借助 A…...

微前端架构学习笔记

前言 之前遇到过一个需求&#xff0c;有两个项目分别由两个不同的部门负责&#xff0c;不同技术栈&#xff0c;不同代码仓库&#xff1a; A 项目是官网&#xff0c;负责展示产品亮点等信息&#xff0c;有多个入口可以进入 B 项目中的不同页面。B 项目是业务线&#xff0c;负责…...

DApp开发:从合约到系统快速上线解决方案

在区块链技术迅猛发展的今天&#xff0c;去中心化应用&#xff08;DApp&#xff09;作为区块链的一项重要应用&#xff0c;已经吸引了众多开发者和企业的关注。与传统应用程序不同&#xff0c;DApp依托于区块链的去中心化特点&#xff0c;实现了透明、安全、不可篡改等优势&…...

react 中 useState 中的 set 方法异步解决

使用 useEffect 监听状态的改变。 一、异步特性 在批量处理状态更新时&#xff0c;用以提高性能。 二、异步解决 使用useEffect来处理更新后的状态&#xff0c;useEffect钩子在组件渲染后执行&#xff0c;并且会在依赖项&#xff08;第二个参数&#xff09;发生变化时重新执…...

UAC2.0 speaker——带反馈端点的 USB speaker(16bit 单声道)

UAC2.0 speaker 系列文章 UAC2.0 speaker——单声道 USB speaker(16bit) UAC2.0 speaker——类特殊请求 UAC2.0 speaker——音量控制 UAC2.0 speaker——多采样率支持 UAC2.0 speaker——24/32bit 支持 UAC2.0 speaker——speaker 数据传输 UAC2.0 speaker——同时支持 16bi…...

docker的简单使用

文章目录 docker简介docker架构镜像和容器镜像有关的常用命令容器相关常用命令 docker简介 Docker是一个开源的应用容器引擎&#xff0c;基于Go语言并遵从Apache2.0协议开源。 Docker可以让开方子打包他们的应用以及依赖包到一个轻量级、可移植的容器中&#xff0c;然后发布到…...

Selenium:强大的 Web 自动化测试工具

Selenium&#xff1a;强大的 Web 自动化测试工具 在当今的软件开发和测试领域&#xff0c;自动化工具的重要性日益凸显。Selenium 就是一款备受欢迎的 Web 自动化测试工具&#xff0c;它为开发者和测试人员提供了强大的功能和便利。本文将详细介绍 Selenium 是什么&#xff0c…...

设计模式 在PLM系统的应用场景介绍

通义灵码 设计模式在 PLM&#xff08;产品生命周期管理&#xff09;系统中扮演着重要的角色&#xff0c;可以帮助开发人员更好地组织代码、提高系统的可维护性和扩展性。以下是一些常见的设计模式及其在 PLM 系统中的应用场景&#xff1a; 1. 单例模式&#xff08;Singleton …...

C#请求https提示未能为 SSL/TLS 安全通道建立信任关系

System.Net.WebException: 基础连接已经关闭: 未能为 SSL/TLS 安全通道建立信任关系 &#xff0c;这个错误通常表明你的应用程序在尝试建立一个安全的 SSL/TLS 连接时遇到了问题。这通常是由于证书验证失败引起的。证书验证失败可能有几个原因&#xff1a; 证书不受信任&#…...

【人工智能】GaussDB数据库技术及应用

文章目录 前言一、数据库的基本概念及发展演进1、数据库概念DB2、数据库管理系统概念DBMS3、数据库与数据库管理系统的关系4、数据库的演进及发展5、数据模型的基本概念6、数据模型的要求和类型7、层次模型的基本概念8、网状模型的基本概念8、关系模型的基本概念9、非关系模型的…...

LeetCode - 394. 字符串解码

题目 394. 字符串解码 - 力扣&#xff08;LeetCode&#xff09; 思路 使用两个栈&#xff1a;一个存储重复次数&#xff0c;一个存储字符串 遍历输入字符串&#xff1a; 数字处理&#xff1a;遇到数字时&#xff0c;累积计算重复次数左括号处理&#xff1a;保存当前状态&a…...

华为OD机试-食堂供餐-二分法

import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...

浅谈不同二分算法的查找情况

二分算法原理比较简单&#xff0c;但是实际的算法模板却有很多&#xff0c;这一切都源于二分查找问题中的复杂情况和二分算法的边界处理&#xff0c;以下是博主对一些二分算法查找的情况分析。 需要说明的是&#xff0c;以下二分算法都是基于有序序列为升序有序的情况&#xf…...

大数据学习(132)-HIve数据分析

​​​​&#x1f34b;&#x1f34b;大数据学习&#x1f34b;&#x1f34b; &#x1f525;系列专栏&#xff1a; &#x1f451;哲学语录: 用力所能及&#xff0c;改变世界。 &#x1f496;如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏⭐️留言&#x1f4…...

React---day11

14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store&#xff1a; 我们在使用异步的时候理应是要使用中间件的&#xff0c;但是configureStore 已经自动集成了 redux-thunk&#xff0c;注意action里面要返回函数 import { configureS…...

佰力博科技与您探讨热释电测量的几种方法

热释电的测量主要涉及热释电系数的测定&#xff0c;这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中&#xff0c;积分电荷法最为常用&#xff0c;其原理是通过测量在电容器上积累的热释电电荷&#xff0c;从而确定热释电系数…...

算法岗面试经验分享-大模型篇

文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer &#xff08;1&#xff09;资源 论文&a…...

人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式

今天是关于AI如何在教学中增强学生的学习体验&#xff0c;我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育&#xff0c;这并非炒作&#xff0c;而是已经发生的巨大变革。教育机构和教育者不能忽视它&#xff0c;试图简单地禁止学生使…...

iview框架主题色的应用

1.下载 less要使用3.0.0以下的版本 npm install less2.7.3 npm install less-loader4.0.52./src/config/theme.js文件 module.exports {yellow: {theme-color: #FDCE04},blue: {theme-color: #547CE7} }在sass中使用theme配置的颜色主题&#xff0c;无需引入&#xff0c;直接可…...

Ubuntu Cursor升级成v1.0

0. 当前版本低 使用当前 Cursor v0.50时 GitHub Copilot Chat 打不开&#xff0c;快捷键也不好用&#xff0c;当看到 Cursor 升级后&#xff0c;还是蛮高兴的 1. 下载 Cursor 下载地址&#xff1a;https://www.cursor.com/cn/downloads 点击下载 Linux (x64) &#xff0c;…...