对象的序列化和反序列化
- 格式:docx
- 大小:15.06 KB
- 文档页数:5
如何在C++中进行数据的序列化和反序列化在C++中进行数据的序列化和反序列化是一种将对象或数据结构转换为可存储或传输的形式的过程,以便在需要时可以将其还原为原始形式。
序列化和反序列化在许多应用程序中都非常重要,特别是在网络通信和数据存储方面。
本文将介绍在C++中进行数据序列化和反序列化的几种方法。
一、序列化和反序列化的概念1.序列化:将对象或数据结构转换为可存储或传输的字节序列的过程。
2.反序列化:将字节序列还原为对象或数据结构的过程。
二、序列化和反序列化的方法1.手动序列化和反序列化这是最常见的方法,即手动编写将对象转换为字节序列的代码,以及将字节序列还原为对象的代码。
下面是一个示例:```cppclass Student {public:std::string name;int age;//手动序列化方法void Serialize(std::ostream& out) {out << name << " " << age << std::endl; }//手动反序列化方法void Deserialize(std::istream& in) {in >> name >> age;}};```这里的`Serialize`和`Deserialize`方法将学生对象的名称和年龄分别转换为字符串,并通过流进行输入和输出。
使用此方法需要手动将每个对象的属性转换为字节序列,并在反序列化时将其还原。
2.使用第三方库当处理复杂的数据结构时,手动编写序列化和反序列化代码可能会非常繁琐和容易出错。
因此,使用第三方库来简化这些任务是很常见的选择。
以下是一些常用的C++序列化库:- Boost.Serialization:Boost库是一个流行的C++库,其中包含了一个功能强大的序列化库。
它可以将C++对象序列化为二进制或XML格式。
Java对象的序列化与反序列化-Json篇说到Java对象的序列化与反序列化,我们⾸先想到的应该是Java的Serializable接⼝,这玩意在两个系统之间的DTO对象⾥⾯可能会⽤到,⽤于系统之间的数据传输。
或者在RPC(远程⽅法调⽤)时可能会⽤到。
但其实若是⽤于数据传输,xml和json两种数据格式⽤得更多⼀些。
但是为什么不⽤XStream呢,XStream确实好⽤,但是在Applet环境下可以使⽤的xml类库也就只有jdom了,连dom4j在Applet环境下都没有权限使⽤(Java反射的某些特性是需要权限的,Applet的安全机制不允许)。
扯远了,本⽂要说的是Java对象与Json的相互转换。
⽬前Java常⽤的Json类库有3种,即fastjson、jackson和gson,分别介绍如何将⼀个Java对象转换成Json和将⼀个Json字符串转换成Java对象,其实它们的⽤法⼤同⼩异。
⼀、⾸先看Maven依赖⼆、需要序列化的POJO和初始化代码三、fastjson的使⽤四、jackson的使⽤五、gson的使⽤⼀、⾸先看Maven依赖若不会maven,请参考Maven的基本⽤法:1 <!-- json -->2 <!-- 引⼊fastjson依赖 -->3 <dependency>4 <groupId>com.alibaba</groupId>5 <artifactId>fastjson</artifactId>6 <version>1.2.12</version>7 </dependency>8 <!-- 引jackson依赖 -->9 <!-- jackson核⼼包,必选,提供基于“流模式”解析的API -->10 <dependency>11 <groupId>com.fasterxml.jackson.core</groupId>12 <artifactId>jackson-core</artifactId>13 <version>2.7.4</version>14 </dependency>15 <!-- jackson注解包,可选,提供注解功能 -->16 <dependency>17 <groupId>com.fasterxml.jackson.core</groupId>18 <artifactId>jackson-annotations</artifactId>19 <version>2.7.4</version>20 </dependency>21 <!-- jackson数据绑定包,可选,提供基于“对象绑定”和“树模型”相关API -->22 <dependency>23 <groupId>com.fasterxml.jackson.core</groupId>24 <artifactId>jackson-databind</artifactId>25 <version>2.7.4</version>26 </dependency>27 <!-- 引⼊gson依赖 -->28 <dependency>29 <groupId>com.google.code.gson</groupId>30 <artifactId>gson</artifactId>31 <version>2.6.2</version>32 </dependency>⼆、需要序列化的POJO和初始化代码以下3种类库的使⽤均使⽤下⾯这个POJO1public class User {2public User(){}3private String id;4private String name;5private String password;6public String getId() {7return id;8 }9public void setId(String id) {10this.id = id;11 }12public String getName() {13return name;14 }15public void setName(String name) { = name;17 }18public String getPassword() {19return password;20 }21public void setPassword(String password) {22this.password = password;23 }24 @Override25public String toString() {26return"User [id=" + id + ", name=" + name + ", password=" + password27 + "]";28 }29 }1/**2 * 初始化User对象3 * @return user4*/5private static User initUser(){6 User user = new User();7 user.setId("1");8 user.setName("jison");9 user.setPassword("jison");10return user;11 }三、fastjson的使⽤fastjson的主要⼯具类是JSON,以下代码实现Java对象的序列化与反序列化1// 将Java对象序列化为Json字符串2 String objectToJson = JSON.toJSONString(initUser());3 System.out.println(objectToJson);4// 将Json字符串反序列化为Java对象5 User user = JSON.parseObject(objectToJson, User.class);6 System.out.println(user);四、jackson的使⽤jackson我们经常⽤到的是它的数据绑定包下的ObjectMapper类,以下代码实现Java对象的序列化与反序列化ObjectMapper objectMapper = new ObjectMapper();// 将Java对象序列化为Json字符串String objectToJson = objectMapper.writeValueAsString(initUser());System.out.println(objectToJson);// 将Json字符串反序列化为Java对象User user = objectMapper.readValue(objectToJson, User.class);System.out.println(user);五、gson的使⽤gson的主要⼯具类是Gson,使⽤GsonBuilder构造,以下代码实现Java对象的序列化与反序列化1 Gson gson = new GsonBuilder().create();2// 将Java对象序列化为Json字符串3 String objectToJson = gson.toJson(initUser());4 System.out.println(objectToJson);5// 将Json字符串反序列化为Java对象6 User user = gson.fromJson(objectToJson, User.class);7 System.out.println(user);以上3种json类库的完整代码如下:1public class JsonUtils {23/**4 * 初始化User对象5 * @return user6*/7private static User initUser(){8 User user = new User();9 user.setId("1");10 user.setName("jison");11 user.setPassword("jison");12return user;13 }1415public static void main(String[] args) throws Exception {16// fastjson⽤法17 fastjson();18// jackson⽤法19 jackson();20// gson⽤法21 gson();22 }2324private static void fastjson(){25// 将Java对象序列化为Json字符串26 String objectToJson = JSON.toJSONString(initUser());27 System.out.println(objectToJson);28// 将Json字符串反序列化为Java对象29 User user = JSON.parseObject(objectToJson, User.class);30 System.out.println(user);31 }3233private static void jackson() throws Exception{34 ObjectMapper objectMapper = new ObjectMapper();35// 将Java对象序列化为Json字符串36 String objectToJson = objectMapper.writeValueAsString(initUser());37 System.out.println(objectToJson);38// 将Json字符串反序列化为Java对象39 User user = objectMapper.readValue(objectToJson, User.class);40 System.out.println(user);41 }4243private static void gson(){44 Gson gson = new GsonBuilder().create();45// 将Java对象序列化为Json字符串46 String objectToJson = gson.toJson(initUser());47 System.out.println(objectToJson);48// 将Json字符串反序列化为Java对象49 User user = gson.fromJson(objectToJson, User.class);50 System.out.println(user);51 }52 }。
序列化与反序列化的原理以及利⽤和防御1、序列化和反序列化的概念序列化:把对象转换为字节序列的过程称为对象的序列化。
反序列化:把字节序列恢复为对象的过程称为对象的反序列化。
序列化就是把对象转换成字节流,便于保存在内存、⽂件、数据库中;反序列化即逆过程,由字节流还原成对象。
Java中的ObjectOutputStream类的writeObject()⽅法可以实现序列化,类ObjectInputStream类的readObject()⽅法⽤于反序列化。
下⾯是将字符串对象先进⾏序列化,存储到本地⽂件,然后再通过反序列化进⾏恢复如果Java应⽤对⽤户输⼊,即不可信数据做了反序列化处理,那么攻击者可以通过构造恶意输⼊,让反序列化产⽣⾮预期的对象,⾮预期的对象在产⽣过程中就有可能带来任意代码执⾏问题的根源在于类ObjectInputStream在反序列化时,没有对⽣成的对象的类型做限制;假若反序列化可以设置Java类型的⽩名单2、序列化的⽬的与⽤到序列化的情况当你想把的内存中的对象状态保存到⼀个⽂件中或者数据库中时候;当你想⽤套接字在⽹络上传送对象的时候;当你想通过RMI传输对象的时候;2.1对象序列化的步骤如下(1)创建对象输⼊流,它可以包装⼀个其他类型的⽬标输⼊流,例如:⽂件输出流。
(2)通过对象输⼊流的writeObject()⽅法写对象。
2.2.对象的反序列化如下:(1)创建对象输⼊流,同样的,可以包含其他类型的⽬标输出流,例如:⽂件输⼊流。
(2)通过对象输⼊流的readObject()⽅法读取对象。
3、漏洞挖掘基本⼿段:从可控数据的反序列化或间接的反序列化接⼝⼊⼿,在此基础上尝试构造序列化对象。
⾸先拿到⼀个Java应⽤,需要找到⼀个接受外部输⼊的序列化对象的接收点,即反序列化漏洞的触发点。
我们可以通过审计源码中对反序列化函数的调⽤(例如readObject())来寻找,也可以直接通过对应⽤交互流量进⾏抓包,查看流量中是否包含java序列化数据来判断,java序列化数据的特征为以标记(ac ed 00 05)开头。
c++对象的序列化与反序列化的解决⽅案----flatbuffers的使⽤概述 本篇blog主要是给⼤家介绍FlatBuffers的相关的信息和⽤法,当我在了解的FlatBuffers时,国内还没有⼀些相关的⽂章去介绍FlatBuffers,不得不FQ去google相关的⽤法,然后理解并应⽤到⾃⼰的代码中,学习的时间成本很⾼。
所以就花了点时间整理⼀份具体的⽤法,提供给⼤家⼀个参考。
简介⼀、什么是FlatBuffers? FlatBuffers是⼀个开源的、跨平台的、⾼效的、提供了C++/Java接⼝的序列化⼯具库。
它是Google专门为游戏开发或其他性能敏感的应⽤程序需求⽽创建。
尤其更适⽤于移动平台,这些平台上内存⼤⼩及带宽相⽐桌⾯系统都是受限的,⽽应⽤程序⽐如游戏⼜有更⾼的性能要求。
它将序列化数据存储在缓存中,这些数据既可以存储在⽂件中,⼜可以通过⽹络原样传输,⽽不需要任何解析开销。
代码托管主页:;项⽬介绍主页:;⼆、FlatBuffers⽤途有哪些? 1、对C++代码的序列化与反序列化:①写本地缓存,⽅便读取。
②⽤于⽹络数据发送。
2、将xml、json⽂件转换成⼆进制⽂件,⼤⼤缩减加载⽂件时间⽤法关于FlatBuffers的⽤法,我下⾯还是通过代码向⼤家讲解,这样更直观,更容易理解。
class Point{float x;float y;};class Node{std::string name;Point position;};class Layer: public Node{Node* friend;std::vector<Node*> children;std::vector<Point *> transform;};1、使⽤前的准备 ⾸先构建⼀个schema⽂件。
schema⽂件主要是记录了我们所要⽤的对象的成员信息。
//>>>>>>>>> schema begin <<<<<<<<<<<namespace Layer;table Point_Fb{x:float; y:float;}table Node_Fb{name:string; position:Point_Fb;}table Layer_Fb{ super:Node_Fb; friend:Node_Fb; children:[Node_Fb]; transform:[Point_Fb];}root_type Layer_Fb;//>>>>>>>>> schema end <<<<<<<<<<<到这⾥我们的schema⽂件已经写完了,然后保存为Layer_Fb.fbs⽂件。
数据序列化和反序列化数据序列化和反序列化是计算机科学中非常重要的概念。
序列化是将一组数据转换为一个特定格式的字符串或字节,以便将其存储在文件或数据库中,或通过网络发送到其他计算机。
反序列化是将序列化后的数据还原为原始的数据结构或对象。
1. 序列化序列化是将数据结构或对象转换为可以持久化的字节序列或其他格式的过程。
在Java语言中,可以使用Java 序列化来完成这一过程。
在.NET框架中,可以使用XML、JSON、二进制格式和SOAP(Web服务)等进行序列化。
Java序列化的实现方式是将对象写入到一个二进制流中。
它需要实现java.io.Serializable接口,并且可以使用ObjectOutputStream进行序列化。
序列化后的数据可以存储到文件、数据库或通过网络发送到其他计算机。
.NET框架提供了多种序列化器。
其中XML序列化器可以将对象序列化为XML格式的字符串。
JSON序列化器可以将对象序列化为JSON格式的字符串。
二进制序列化器可以将对象序列化为二进制格式的字节数组。
SOAP序列化器可以将对象序列化为XML格式的SOAP消息。
序列化是一种重要的技术,可以用于数据的存储、传输以及远程方法调用等方面。
但是,在使用序列化时需要注意以下几点:(1)序列化的数据格式应该尽量小且简洁,以节省存储和传输带宽。
(2)序列化的数据应该具有跨平台和可移植性,以便于跨不同系统和语言进行数据交换。
(3)序列化的对象必须是可序列化的,即序列化的对象必须实现特定的接口或约定。
(4)由于序列化的过程可能带来性能损失,因此需要仔细考虑序列化的时间和代价。
2. 反序列化反序列化是将序列化后的数据还原为原始的数据结构或对象的过程。
在Java语言中,可以使用ObjectInputStream进行反序列化。
在.NET框架中,可以使用相应的反序列化器进行反序列化。
反序列化的过程是将二进制数据流转换为原始数据类型或对象的过程。
反序列化函数
一,列化与反序列化
序列化就是把一个对象变成可以传输的字符串,可以以特定的格式在进程之间跨平台(像JAVA---PHP)、安全的通信。
可以理解为将类(class)中的对象(object)由内存中的抽象数据结构,用序列化的字符串保存在硬盘(或数据库,如redis中),从而缓解内存压力,等到用的时候,再从硬盘反序列化到内存调用。
序列化:对象转化为字符串。
反序列化:字符串转化为对象。
在反序列化过程中会触发代码执行。
二、反序列化漏洞
PHP反序列化漏洞也叫PHP对象注入,属于常见漏洞。
形成原因程序员没有对用户输入的反序列化字符串进行检测,导致反序列化过程可以被恶意控制,进而造成代码执行、getshell等一些列不可控的后果。
反序列化漏洞并不是PHP特有的,也存在JAVA、PYTHON,原理基本相通。
JSON:格式化的字符串。
输出健值对的数据形式,类似于Python的字典。
序列化函数:serialize
反序列化函数:unserialize。
"pkl"是一个缩写,通常用来表示Python编程语言中的一种数据序列化文件格式。
具体来说,"pkl"是"pickle"的缩写,它是Python标准库中的一个模块,用于实现Python对象的序列化和反序列化。
解释:
序列化:在计算机科学中,序列化是指将数据结构或对象转换为一种特定格式的字节流,以便在不同系统之间传输或存储。
序列化后的数据可以保存到文件中或通过网络传输。
在Python中,通过使用pickle模块,可以将Python对象序列化为字节流。
反序列化:反序列化是将序列化后的字节流重新转换回原始数据结构或对象的过程。
在Python中,可以使用pickle模块将序列化的数据重新转换为Python对象。
pickle模块提供了dump()和load()函数来实现序列化和反序列化。
通过pickle模块,可以方便地将复杂的Python对象,如字典、列表、类的实例等,转换为字节流并保存到文件中,或者从文件中读取字节流并还原为原始对象。
由于pickle生成的字节流是Python特定的,因此在跨语言或不同版本的Python之间进行序列化和反序列化时需要小心。
在这种情况下,可以选择使用其他通用的数据交换格式,如JSON或XML。
iiop和t3反序列化原理。
序列化是将对象转换为字节流的过程,而反序列化则是将字节流转换为对象的过程。
在网络通信中,常常需要将对象进行序列化后传输,然后在接收端进行反序列化恢复成对象。
iiop和t3是两种常用的网络协议,它们都支持对象的序列化和反序列化。
iiop是Internet Inter-Orb Protocol的缩写,是一种面向对象的协议,用于分布式对象之间的通信。
iiop使用统一的接口定义语言(Interface Definition Language,IDL)来描述对象的接口,以及对象之间的调用关系。
iiop支持对象的序列化和反序列化,即将对象转换为字节流进行传输,然后在接收端进行反序列化恢复成对象。
iiop的序列化和反序列化过程如下:1. 对象序列化:将要传输的对象按照一定的规则转换为字节流。
首先,将对象的类名和属性列表转换为字节流;然后,按照属性的类型和取值将每个属性转换为字节流;最后,将转换后的字节流进行拼接,得到最终的序列化字节流。
2. 对象反序列化:将接收到的字节流按照一定的规则转换为对象。
首先,从字节流中读取类名和属性列表;然后,按照属性的类型和取值从字节流中读取每个属性的值;最后,根据类名和属性值,创建对象并赋值。
iiop的序列化和反序列化过程中,需要注意以下几点:1. 序列化和反序列化的规则必须一致,否则会导致数据不一致或无法解析的问题。
2. 序列化和反序列化的性能往往会影响整个系统的性能,因此需要选择高效的序列化和反序列化算法。
3. 序列化和反序列化的过程中,需要考虑对象的版本兼容性,即在对象发生变化时能够正确地进行序列化和反序列化。
t3是Oracle WebLogic Server使用的一种网络协议,用于分布式对象之间的通信。
t3协议基于iiop协议,但又进行了一些扩展和优化。
t3支持对象的序列化和反序列化,以及对象之间的远程调用。
t3的序列化和反序列化过程与iiop类似,但在具体实现上可能有所不同。
deserializeobject和serializeobject什么是deserializeObject和serializeObject?在软件开发中,对象的序列化和反序列化是常见的操作。
简单地说,序列化(serialize)就是将对象转换为字节流,以便于存储或传输;反序列化(deserialize)则是将字节流转换回对象。
其中,deserializeObject和serializeObject是两个常用的方法或函数,用于实现对象的反序列化和序列化。
为什么需要对象的序列化和反序列化?在很多场景中,需要将对象以某种方式进行持久化存储或者进行网络传输。
而对象本身是无法直接存储或传输的,因为对象是存储在内存中的,而存储或传输的是字节流或者文本数据。
因此,需要将对象序列化为字节流,以便于存储或传输。
而反序列化则是将字节流转换回对象,以便于在程序中使用。
如何使用deserializeObject和serializeObject?使用deserializeObject和serializeObject方法的具体实现可能会因编程语言的不同而有所差异。
以下是针对Java语言的解释:deserializeObject方法用于将字节流转换回对象。
在Java中,可以通过ObjectInputStream类来实现该方法。
首先,需要创建一个字节输入流(InputStream),然后使用它来初始化ObjectInputStream对象。
然后,可以使用ObjectInputStream对象的readObject方法来读取字节流,并将其转换为对象。
最后,需要使用强制类型转换将结果转换为所需的对象类型。
以下是一个示例代码:InputStream inputStream = new FileInputStream("data.ser"); ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);Object object = objectInputStream.readObject(); objectInputStream.close();强制类型转换MyObject myObject = (MyObject) object;serializeObject方法用于将对象转换为字节流。
JAXB序列化对象与反序列化XML1、什么是JAXBJAXB(Java Architecture for XML Binding) 是⼀个业界的标准,是⼀项可以根据XML Schema产⽣Java类的技术。
该过程中,JAXB也提供了将XML实例⽂档反向⽣成Java对象树的⽅法,并能将Java对象树的内容重新写到XML实例⽂档。
从另⼀⽅⾯来讲,JAXB提供了快速⽽简便的⽅法将XML模式绑定到Java表⽰,从⽽使得Java开发者在Java应⽤程序中能⽅便地结合XML数据和处理函数。
2、JAR下载3、Demo解决字段包含⼦类,list集合序列化根节点RequestVO.javaimport java.util.List;import javax.xml.bind.annotation.XmlAccessType;import javax.xml.bind.annotation.XmlAccessorType;import javax.xml.bind.annotation.XmlElementWrapper;import javax.xml.bind.annotation.XmlRootElement;import javax.xml.bind.annotation.XmlType;@XmlAccessorType(XmlAccessType.FIELD)//XML⽂件中的根标识@XmlRootElement(name = "request")//控制JAXB 绑定类中属性和字段的排序@XmlType(propOrder = {"entryOrder","orderLine"})/*** ⽣产XML根节点* @author Stephen* @Time 2019年6⽉27⽇09:49:36* */public class RequestVO {private EntryOrder entryOrder;@XmlElementWrapper(name = "orderLines")private List<OrderLine> orderLine;public EntryOrder getEntryOrder() {return entryOrder;}public void setEntryOrder(EntryOrder entryOrder) {this.entryOrder = entryOrder;}public List<OrderLine> getOrderLine() {return orderLine;}public void setOrderLine(List<OrderLine> orderLine) {this.orderLine = orderLine;}}EntryOrder.javaimport javax.xml.bind.annotation.XmlAccessType;import javax.xml.bind.annotation.XmlAccessorType;import javax.xml.bind.annotation.XmlRootElement;import javax.xml.bind.annotation.XmlType;@XmlAccessorType(XmlAccessType.FIELD)//XML⽂件中的根标识@XmlRootElement(name = "entryOrder")//控制JAXB 绑定类中属性和字段的排序@XmlType(propOrder = {"totalOrderLines","entryOrderCode","ownerCode","warehouseCode","entryOrderId","entryOrderType","outBizCode","confirmType","status","operateTime","remark"})/*** ⼦节点* @author Stephen* @Time 2019年6⽉27⽇09:49:36* */public class EntryOrder {public String totalOrderLines;public String entryOrderCode;public String ownerCode;public String warehouseCode;public String entryOrderId;public String entryOrderType;public String outBizCode;public String confirmType;public String status;public String operateTime;public String remark;public EntryOrder() {this.totalOrderLines = "";this.entryOrderCode = "";this.ownerCode = "";this.warehouseCode = "";this.entryOrderId = "";this.entryOrderType = "";this.outBizCode = "";this.confirmType = "";this.status = "";this.operateTime = "";this.remark = "";}public String getTotalOrderLines() {return totalOrderLines;}public void setTotalOrderLines(String totalOrderLines) {this.totalOrderLines = totalOrderLines;}public String getEntryOrderCode() {return entryOrderCode;}public void setEntryOrderCode(String entryOrderCode) {this.entryOrderCode = entryOrderCode;}public String getOwnerCode() {return ownerCode;}public void setOwnerCode(String ownerCode) {this.ownerCode = ownerCode;}public String getWarehouseCode() {return warehouseCode;}public void setWarehouseCode(String warehouseCode) { this.warehouseCode = warehouseCode;}public String getEntryOrderId() {return entryOrderId;}public void setEntryOrderId(String entryOrderId) {this.entryOrderId = entryOrderId;}public String getEntryOrderType() {return entryOrderType;}public void setEntryOrderType(String entryOrderType) {this.entryOrderType = entryOrderType;}public String getOutBizCode() {return outBizCode;}public void setOutBizCode(String outBizCode) {this.outBizCode = outBizCode;}public String getConfirmType() {return confirmType;}public void setConfirmType(String confirmType) {this.confirmType = confirmType;}public String getStatus() {return status;}public void setStatus(String status) {this.status = status;}public String getOperateTime() {return operateTime;}public void setOperateTime(String operateTime) {this.operateTime = operateTime;}public String getRemark() {return remark;}public void setRemark(String remark) {this.remark = remark;}}OrderLine.javaimport java.util.List;import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType;@XmlAccessorType(XmlAccessType.FIELD)//XML⽂件中的根标识@XmlRootElement(name = "orderLine")//控制JAXB 绑定类中属性和字段的排序@XmlType(propOrder = {"outBizCode","orderLineNo","ownerCode","itemCode","itemId","itemName","inventoryType","imperfectGrade","planQty","actualQty","batchCode","productDate","expireDate","produceCode","batch","remark"})public class OrderLine {private String outBizCode;private String orderLineNo;private String ownerCode;private String itemCode;private String itemId;private String itemName;private String inventoryType;private String imperfectGrade;private String planQty;private String actualQty;private String batchCode;private String productDate;private String expireDate;private String produceCode;@XmlElementWrapper(name = "batchs")private List<Batch> batch;private String remark;public OrderLine() {this.outBizCode = "";this.orderLineNo = "";this.ownerCode = "";this.itemCode = "";this.itemId = "";this.itemName = "";this.inventoryType = "";this.imperfectGrade = "";this.planQty = "";this.actualQty = "";this.batchCode = "";this.productDate = "";this.expireDate = "";this.produceCode = "";this.remark = "";}public List<Batch> getBatchs() {return batch;}public void setBatchs(List<Batch> batchs) {this.batch = batchs;}public String getRemark() {return remark;}public void setRemark(String remark) {this.remark = remark;}public String getOutBizCode() {return outBizCode;}public void setOutBizCode(String outBizCode) {this.outBizCode = outBizCode;}public String getOrderLineNo() {return orderLineNo;}public void setOrderLineNo(String orderLineNo) {this.orderLineNo = orderLineNo;}public String getOwnerCode() {return ownerCode;}public void setOwnerCode(String ownerCode) {this.ownerCode = ownerCode;}public String getItemCode() {return itemCode;}public void setItemCode(String itemCode) {this.itemCode = itemCode;}public String getItemId() {return itemId;}public void setItemId(String itemId) {this.itemId = itemId;}public String getItemName() {return itemName;}public void setItemName(String itemName) {this.itemName = itemName;}public String getInventoryType() {return inventoryType;}public void setInventoryType(String inventoryType) {this.inventoryType = inventoryType;}public String getImperfectGrade() {return imperfectGrade;}public void setImperfectGrade(String imperfectGrade) { this.imperfectGrade = imperfectGrade;}public String getPlanQty() {return planQty;}public void setPlanQty(String planQty) {this.planQty = planQty;}public String getActualQty() {return actualQty;}public void setActualQty(String actualQty) {this.actualQty = actualQty;}public String getBatchCode() {return batchCode;}public void setBatchCode(String batchCode) {this.batchCode = batchCode;}public String getProductDate() {return productDate;}public void setProductDate(String productDate) {this.productDate = productDate;}public String getExpireDate() {return expireDate;}public void setExpireDate(String expireDate) {this.expireDate = expireDate;}public String getProduceCode() {return produceCode;}public void setProduceCode(String produceCode) {this.produceCode = produceCode;}}Batch.javaimport javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType;@XmlAccessorType(XmlAccessType.FIELD)//XML⽂件中的根标识@XmlRootElement(name = "batch")//控制JAXB 绑定类中属性和字段的排序@XmlType(propOrder = {"batchCode","productDate","expireDate","produceCode","inventoryType","imperfectGrade","actualQty"})public class Batch {private String batchCode;private String productDate;private String expireDate;private String produceCode;private String inventoryType;private String imperfectGrade;private String actualQty;public Batch() {this.batchCode = "";this.productDate = "";this.expireDate = "";this.produceCode = "";this.inventoryType = "";this.imperfectGrade = "";this.actualQty = "";}public String getBatchCode() {return batchCode;}public void setBatchCode(String batchCode) {this.batchCode = batchCode;}public String getProductDate() {return productDate;}public void setProductDate(String productDate) {this.productDate = productDate;}public String getExpireDate() {return expireDate;}public void setExpireDate(String expireDate) {this.expireDate = expireDate;}public String getProduceCode() {return produceCode;}public void setProduceCode(String produceCode) {this.produceCode = produceCode;}public String getInventoryType() {return inventoryType;}public void setInventoryType(String inventoryType) {this.inventoryType = inventoryType;}public String getImperfectGrade() {return imperfectGrade;}public void setImperfectGrade(String imperfectGrade) { this.imperfectGrade = imperfectGrade;}public String getActualQty() {return actualQty;}public void setActualQty(String actualQty) {this.actualQty = actualQty;}}JAXBUtil.javaimport java.io.StringReader;import java.io.StringWriter;import javax.xml.bind.JAXBContext;import javax.xml.bind.JAXBException;import javax.xml.bind.Marshaller;import javax.xml.bind.Unmarshaller;/*** @Description:xml和对象相互转换⼯具类* @author:yaolong* @data:2017年2⽉9⽇下午10:46:57* @version:1.0*/public class JAXBUtil {/*** JavaBean转换成xml 默认编码UTF-8** @param obj* @param writer* @return*/public static String convertToXml(Object obj) {return convertToXml(obj, "UTF-8");}/*** JavaBean转换成xml** @param obj* @param encoding* @return*/public static String convertToXml(Object obj, String encoding) {String result = null;try {JAXBContext context = JAXBContext.newInstance(obj.getClass());Marshaller marshaller = context.createMarshaller();marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);marshaller.setProperty(Marshaller.JAXB_ENCODING, encoding);marshaller.setProperty(Marshaller.JAXB_FRAGMENT, false);// 是否省略xml头信息 StringWriter writer = new StringWriter();marshaller.marshal(obj, writer);result = writer.toString();} catch (Exception e) {e.printStackTrace();}return result;}/*** xml转换成JavaBean* @param xml* @param c* @return* @throws JAXBException*/@SuppressWarnings("unchecked")public static <T> T converyToJavaBean(String xml, Class<T> c)throws JAXBException {T t = null;JAXBContext context = JAXBContext.newInstance(c);Unmarshaller unmarshaller = context.createUnmarshaller();t = (T) unmarshaller.unmarshal(new StringReader(xml));return t;}}XML格式<?xml version="1.0" encoding="utf-8"?><request><entryOrder><totalOrderLines></totalOrderLines><entryOrderCode></entryOrderCode><ownerCode></ownerCode><warehouseCode></warehouseCode><entryOrderId></entryOrderId><entryOrderType></entryOrderType><outBizCode></outBizCode><confirmType></confirmType><status></status><operateTime></operateTime><remark></remark></entryOrder><orderLines><orderLine><outBizCode></outBizCode><orderLineNo></orderLineNo><ownerCode></ownerCode><itemCode></itemCode><itemId></itemId><itemName></itemName><inventoryType></inventoryType><imperfectGrade></imperfectGrade><planQty></planQty><actualQty></actualQty><batchCode></batchCode><productDate></productDate><expireDate></expireDate><produceCode></produceCode><batchs><batch><batchCode></batchCode><productDate></productDate><expireDate></expireDate><produceCode></produceCode><inventoryType></inventoryType><imperfectGrade></imperfectGrade><actualQty></actualQty></batch></batchs><remark></remark></orderLine></orderLines></request>ps:此⽰例都是针对于字符串的操作,重要的是Util。
当两个进程在进行远程通信时,彼此可以发送各种类型的数据。
无论是何种类型的数据,都会以二进制序列的形式在网络上传送。
发送方需要把这个Java对象转换为字节序列,才能在网络上传送;接收方则需要把字节序列再恢复为Java对象。
把Java对象转换为字节序列的过程称为对象的序列化。
把字节序列恢复为Java对象的过程称为对象的反序列化。
对象的序列化主要有两种用途:
1)把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;
2)在网络上传送对象的字节序列。
一.JDK类库中的序列化API
java.io.ObjectOutputStream代表对象输出流,它的writeObject(Object obj)方法可对参数指定的obj对象进行序列化,把得到的字节序列写到一个目标输出流中。
java.io.ObjectInputStream代表对象输入流,它的readObject()方法从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。
、
只有实现了Serializable和Externalizable接口的类的对象才能被序列化。
Externalizable接口继承自Serializable接口,实现Externalizable接口的类完全由自身来控制序列化的行为,而仅实现Serializable接口的类可以采用默认的序列化方式。
对象序列化包括如下步骤:
1)创建一个对象输出流,它可以包装一个其他类型的目标输出流,如文件输出流;
2)通过对象输出流的writeObject()方法写对象。
对象反序列化的步骤如下:
1)创建一个对象输入流,它可以包装一个其他类型的源输入流,如文件输入流;
2)通过对象输入流的readObject()方法读取对象。
下面让我们来看一个对应的例子,类的内容如下:
import java.io.*;
import java.util.Date;
public class ObjectSaver {
public static void main(String[] args) throws Exception { ObjectOutputStream out = new ObjectOutputStream (new FileOutputStream("D:""objectFile.obj"));
//序列化对象
Customer customer = new Customer("阿蜜果", 24);
out.writeObject("你好!");
out.writeObject(new Date());
out.writeObject(customer);
out.writeInt(123); //写入基本类型数据
out.close();
//反序列化对象
ObjectInputStream in = new ObjectInputStream
(new FileInputStream("D:""objectFile.obj"));
System.out.println("obj1=" + (String) in.readObject());
System.out.println("obj2=" + (Date) in.readObject());
Customer obj3 = (Customer) in.readObject();
System.out.println("obj3=" + obj3);
int obj4 = in.readInt();
System.out.println("obj4=" + obj4);
in.close();
}
}
class Customer implements Serializable {
private String name;
private int age;
public Customer(String name, int age) {
= name;
this.age = age;
}
public String toString() {
return "name=" + name + ", age=" + age;
}
}
输出结果如下:
obj1=你好!
obj2=Sat Sep 15 22:02:21 CST 2007
obj3=name=阿蜜果, age=24
obj4=123
因此例比较简单,在此不再详述。
二.实现Serializable接口
ObjectOutputStream只能对Serializable接口的类的对象进行序列化。
默认情况下,ObjectOutputStream按照默认方式序列化,这种序列化方式仅仅对对象的非transient的实例变量进行序列化,而不会序列化对象的transient的实例变量,也不会序列化静态变量。
当ObjectOutputStream按照默认方式反序列化时,具有如下特点:
1)如果在内存中对象所属的类还没有被加载,那么会先加载并初始化这个类。
如果在classpath中不存在相应的类文件,那么会抛出ClassNotFoundException;
2)在反序列化时不会调用类的任何构造方法。
如果用户希望控制类的序列化方式,可以在可序列化类中提供以下形式的writeObject()和readObject()方法。
private void writeObject(java.io.ObjectOutputStream out) throws IOException
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException;
当ObjectOutputStream对一个Customer对象进行序列化时,如果该对象具有writeObject()方法,那么就会执行这一方法,否则就按默认方式序列化。
在该对象的writeObjectt()方法中,可以先调用ObjectOutputStream的defaultWriteObject()方法,使得对象输出流先执行默认的序列化操作。
同理可得出反序列化的情况,不过这次是defaultReadObject()方法。
有些对象中包含一些敏感信息,这些信息不宜对外公开。
如果按照默认方式对它们序列化,那么它们的序列化数据在网络上传输时,可能会被不法份子窃取。
对于这类信息,可以对它们进行加密后再序列化,在反序列化时则需要解密,再恢复为原来的信息。
默认的序列化方式会序列化整个对象图,这需要递归遍历对象图。
如果对象图很复杂,递归遍历操作需要消耗很多的空间和时间,它的内部数据结构为双向列表。
在应用时,如果对某些成员变量都改为transient类型,将节省空间和时间,提高序列化的性能。
三.实现Externalizable接口
Externalizable接口继承自Serializable接口,如果一个类实现了Externalizable接口,那么将完全由这个类控制自身的序列化行为。
Externalizable接口声明了两个方法:
public void writeExternal(ObjectOutput out) throws IOException
public void readExternal(ObjectInput in) throws IOException , ClassNotFoundException
前者负责序列化操作,后者负责反序列化操作。
在对实现了Externalizable接口的类的对象进行反序列化时,会先调用类的不带参数的构造方法,这是有别于默认反序列方式的。
如果把类的不带参数的构造方法删除,或者把该构造方法的访问权限设置为private、默认或protected级别,会抛出java.io.InvalidException: no valid
constructor异常。
四.可序列化类的不同版本的序列化兼容性
凡是实现Serializable接口的类都有一个表示序列化版本标识符的静态变量:
private static final long serialVersionUID;
以上serialVersionUID的取值是Java运行时环境根据类的内部细节自动生成的。
如果对类的源代码作了修改,再重新编译,新生成的类文件的serialVersionUID的取值有可能也会发生变化。
类的serialVersionUID的默认值完全依赖于Java编译器的实现,对于同一个类,用不同的Java 编译器编译,有可能会导致不同的serialVersionUID,也有可能相同。
为了提高哦啊serialVersionUID的独立性和确定性,强烈建议在一个可序列化类中显示的定义serialVersionUID,为它赋予明确的值。
显式地定义serialVersionUID有两种用途:
1)在某些场合,希望类的不同版本对序列化兼容,因此需要确保类的不同版本具有相同的serialVersionUID;
2)在某些场合,不希望类的不同版本对序列化兼容,因此需要确保类的不同版本具有不同的serialVersionUID。