文章目录
一,什么是序列化
对象序列化:是一个用于将对象状态转换为二进制字节流的过程,
持久化:可以将其保存到磁盘文件中或通过网络发送到任何其他程序;
反序列化:从字节流创建对象的相反的过程称为反序列化。
二,常用序列化方式
方式一:要传递的类实现Serializable接口传递对象(Java自带)
ObjectOutputStream 类用来序列化一个对象,使用ObjectOutputStream对象的writeObject()方法来进行对象的写入。
示例:
import java.io.*;
public class SerializeDemo
{
public static void main(String [] args)
{
Employee e = new Employee();
e.name = "Reyan Ali";
e.address = "Phokka Kuan, Ambehta Peer";
e.SSN = 11122333;
e.number = 101;
try
{
FileOutputStream fileOut =
new FileOutputStream("/tmp/employee.ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(e);
out.close();
fileOut.close();
System.out.printf("Serialized data is saved in /tmp/employee.ser");
}catch(IOException i)
{
i.printStackTrace();
}
}
}
反序列化:使用ObjectInputStream对象的readObject()方法来读取对象。
import java.io.*;
public class DeserializeDemo
{
public static void main(String [] args)
{
Employee e = null;
try
{
FileInputStream fileIn = new FileInputStream("/tmp/employee.ser");
ObjectInputStream in = new ObjectInputStream(fileIn);
e = (Employee) in.readObject();
in.close();
fileIn.close();
}catch(IOException i)
{
i.printStackTrace();
return;
}catch(ClassNotFoundException c)
{
System.out.println("Employee class not found");
c.printStackTrace();
return;
}
System.out.println("Deserialized Employee...");
System.out.println("Name: " + e.name);
System.out.println("Address: " + e.address);
System.out.println("SSN: " + e.SSN);
System.out.println("Number: " + e.number);
}
}
忽略某个字段不序列化:
-
使用关键字 transient
-
使用注解 @jsonignore
-
父类实现了序列化,子类未实现但是继承了父类,则子类默认实现序列化
-
子类中添加writeObject和readObject 和 readObjectNoDate()抛出异常。此时子类就不会默认实现序列化。
-
子类实现序列化接口,父类未实现,也需要在父类中添加无参构造函数,并添加writeObject和readObject方法
-
writeObject和readObject方法 是因为通过反射序列化和反序列化
-
无参构造函数:只通过无参构造函数来拿到实例
方式二:要传递的类实现Parcelable接口传递对象(android专用)
实现
复写describeContents方法和writeToParcel方法
2、实例化静态内部对象CREATOR,实现接口Parcelable.Creator
3、自定义构造方法,私有变量的set与get
public class Pen implements Parcelable{
private String color;
private int size;
// 系统自动添加,给createFromParcel里面用
protected Pen(Parcel in) {
color = in.readString();
size = in.readInt();
}
public static final Creator<Pen> CREATOR = new Creator<Pen>() {
/**
*
* @param in
* @return
* createFromParcel()方法中我们要去读取刚才写出的name和age字段,
* 并创建一个Person对象进行返回,其中color和size都是调用Parcel的readXxx()方法读取到的,
* 注意这里读取的顺序一定要和刚才写出的顺序完全相同。
* 读取的工作我们利用一个构造函数帮我们完成了
*/
@Override
public Pen createFromParcel(Parcel in) {
return new Pen(in); // 在构造函数里面完成了 读取 的工作
}
//供反序列化本类数组时调用的
@Override
public Pen[] newArray(int size) {
return new Pen[size];
}
};
@Override
public int describeContents() {
return 0; // 内容接口描述,默认返回0即可。
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(color); // 写出 color
dest.writeInt(size); // 写出 size
}
// ======分割线,写写get和set
//个人自己添加
public Pen() {
}
//个人自己添加
public Pen(String color, int size) {
this.color = color;
this.size = size;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
}
两种方式对比
需要在多个部件(Activity或Service)之间通过Intent传递一些数据,简单类型(如:数字、字符串)的可以直接放入Intent。复杂类型必须实现Parcelable接口。
1)在使用内存的时候,Parcelable比Serializable性能高,所以推荐使用Parcelable。Parcelable是再内存中完成序列化和反序列化的。
2)Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC。
3)Parcelable不能使用在要将数据存储在磁盘上的情况,因为Parcelable不能很好的保证数据的持续性在外界有变化的情况下。尽管Serializable效率低点,但此时还是建议使用Serializable 。
三,Json解析
1,定义
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式
2,作用与特点
作用:数据标记,存储,传输
特点:
1.读写速度快
2. 解析简单
3. 轻量级
4. 独立于语言,平台
3,Json常见形式
1,Object
对象是一个无序的“‘名称/值’对”集合。一个对象以“{”(左括号)开始,“}”(右括号)结束。每个“名称”后跟一个“:”(冒号);“‘名称/值’ 对”之间使用“,”(逗号)分隔。
示例:
{
"name": "英语",
"score": 78.3
}
Array形式
数组是值(value)的有序集合。一个数组以“[”(左中括号)开始,“]”(右中括号)结束。值之间使用“,”(逗号)分隔。
示例:
"courses": [
{
"name": "英语",
"score": 78.3
}
]
3,value
值(value)可以是双引号括起来的字符串(string)、数值(number)、 true 、 false 、 null 、对象(object)或者数组(array)。这些结构可以嵌套。
示例:
{
"url": "https://qqe2.com",
"name": "欢迎使用JSON在线解析编辑器",
"array": {
"JSON校验": "http://jsonlint.qqe2.com/",
"Cron生成": "http://cron.qqe2.com/",
"JS加密解密": "http://edit.qqe2.com/"
},
"boolean": true,
"null": null,
"number": 123,
"object": {
"a": "b",
"c": "d",
"e": "f"
}
}
Json解析器
1,Json-lib
- 原理:解析原理:基于文档驱动,需要把全部文件读入到内存中,然后遍历所有数据,根据需要检索想要的数据
2,Gson
解析流程:根据所需取的数据 建立1个对应于JSON数据的JavaBean类,即可通过简单操作解析出所需数据
Gson 不要求JavaBean类里面的属性一定全部和JSON数据里的所有key相同,可以按需取数据具体实现
序列化:Gson().toJson(object)
反序列化:Gson().fromJson(Json, Simple.class)
@Expose注解是可选择的并且提供了两个配置参数:serialize和deserialize
serialize = true 表示可以序列化, 反之不行
deserialize = true 表示可以反序列化,反之不行
Transient 关键字表示忽略此字段。不会序列化和反序列化
@SerializedName注解改变域名 ,返回fullName,但是用时为name
public class UserSimple {
@SerializedName("fullName")
String name;
String email;
boolean isDeveloper;
int age;
}
public class UserSimpleSerializedName {
@SerializedName(value = "fullName", alternate = "username")
private String name;
private String email;
private boolean isDeveloper;
private int age;
}
在上面的模型类中,Gson将会检查到来的JSON中是否含有fullName或者username。无论是哪一个,都会映射到name属性
Gson的介绍与使用引入此篇文章
https://www.jianshu.com/p/923a9fe78108
3,FastJson
https://juejin.cn/post/6844904176003072007#heading-21
序列化:JSON.toJSONString(simple)
反序列化:
(1)JSON.parseObjec(Json, Simple.class)
(2)JSON.parseObject(JSON_OBJ_STR, new TypeReference() {})
(3)JSON.parseObject(JSON_OBJ_STR);
4,JackSon
解析过程:
- 类似 GSON,先创建1个对应于JSON数据的JavaBean类,再通过简单操作即可解析
- 与 Gson解析不同的是:GSON可按需解析,即创建的JavaBean类不一定完全涵盖所要解析
的JSON数据,按需创建属性;但Jackson解析对应的JavaBean必须把Json数据里面的所有key
都有所对应,即必须把JSON内的数据所有解析出来,无法按需解析
序列化:String json = JsonUtils.toJsonString(user);
反序列化: User u = JsonUtils.parse(json, User.class);