Android基础学习(十五)—— 序列化与反序列化(包括 JSON、GSON))
序列化: 將對象的內容進行流化,將數據分解成字節流,以便存儲在文件中或在網絡上傳輸。對象->字節序列
反序列化: 數據轉化為對象。字節序列->對象
一、序列化簡介
1、進行序列化的原因:
(1)網絡傳輸
網絡傳輸的數據都必須是二進制數據,但是在Java中都是對象,是沒有辦法在網絡中傳輸的,所以就需要對Java對象進行序列化,并且要求這個序列化是可逆的,也就是說要可以進行反序列化,否則人家都不知道你傳遞的是啥信息
(2)對象持久化
將內存中的對象狀態保存到文件或者數據庫中
(3)實現分布式對象
如RMI(遠程方法調用)要利用對象序列化運行遠程主機上的服務,就像在本地機上運行對象時一樣
2、實現序列化的方式
(1)Java原生序列化
需要被序列化的類實現Serializable接口
具體實現:
1)序列化
ObjectOutputStream#writeObject(Object obj)方法
2)反序列化
ObjectInputStream#readObject()方法
缺點:
效率較低,序列化后的流數據比較大
(2)使用第三方的序列化方式
如JSON、Hessian等
3、注意
(1)transient修飾的屬性,是不會被序列化的
(2)靜態static修飾的屬性,是不會被序列化的
二、JSON
JSON(JavaScript Object Notation)是一種輕量級的數據交換格式。易于人閱讀和編寫,同時也易于機器解析和生成。
注意:
1)雖然 JSON 名稱中有 JavaScript,但是 JSON 和 JavaScript 的關系僅僅只是 在設計JSON的時候參照了JavaScript的一些語法而已,兩者無必然聯系。
2)JSON常用于網絡數據的交互,以及將某些數據按照JSON的格式寫入到文件進行持久化記錄
三、GSON
Github:https://github.com/google/gson
GSON是Google提供的用來在Java對象和JSON數據之間進行映射的Java類庫。可以將一個JSON字符串轉成一個Java對象(反序列化),或反過來(序列化)
在項目中引用GSON:
Gradle:
dependencies{implementation 'com.google.code.gson:gson:2.9.1' }1、將對象轉換為JSON字符串
在需要轉換JSON字符串的位置編寫代碼:
String json = new Gson().toJSON(要轉換的對象);2、將JSON字符串轉換為對象
在需要轉換Java對象的位置編寫代碼:
對象 = new Gson().fromJson(JSON字符串, 對象類型.class);接下來,將從以下幾個方面來介紹 GSON 的使用:
- Java Object 序列化/反序列化
- Array 和 List 的序列化/反序列化
- Map 和 Set 的序列化/反序列化
- 變量值為null時的序列化/反序列化
- 控制 序列化/反序列化 的變量名稱
1、Java對象序列化與反序列化
public class User {@Exposeprivate String userName;@Exposeprivate String password;@Exposeprivate int age;@Exposeprivate boolean isStudent;@Exposeprivate Job job;//serialize,是否參與序列化;deserialize,是否參與反序列化@Expose(serialize=false, deserialize=false)private int test1;private transient int test2;//無法以class作為字段名@SerializedName("class")private int cls;public User(String userName, String password, int age, boolean isStudent){this.userName = userName;this.password = password;this.age = age;this.isStudent = isStudent;}public String getUserName() {return userName;}public void setUserName(String userName) {this.userName = userName;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public boolean isStudent() {return isStudent;}public void setStudent(boolean student) {isStudent = student;}public Job getJob() {return job;}public void setJob(Job job) {this.job = job;}public int getTest1() {return test1;}public void setTest1(int test1) {this.test1 = test1;}public int getTest2() {return test2;}public void setTest2(int test2) {this.test2 = test2;}public int getCls() {return cls;}public void setCls(int cls) {this.cls = cls;}@NonNull@Overridepublic String toString() {return "userName=" + userName + ", " +"password=" + password + ", " +"age=" + age + ", " +"isStudent=" + isStudent + ", " +"job=" + job + ", " +"test1=" + test1 + ", " +"test2=" + test2 + ", " +"cls=" + cls;} public class ObjectUnitTest {public void testObject(){User u1 = new User("Lance", "123", 18, false);Gson gson = new Gson();//序列化String json = gson.toJson(u1);System.out.println("序列化:" + json);//反序列化User u2 = gson.fromJson(json, User.class);System.out.println("反序列化:" + u2.getUserName());System.out.println("反序列化:u2: " + u2);}public static void main(String args[]){ObjectUnitTest out = new ObjectUnitTest();out.testObject();} }結果:
序列化:{"userName":"Lance","password":"123","age":18,"isStudent":false,"test1":0,"class":0} 反序列化:u2: userName=Lance, password=123, age=18, isStudent=false, job=null, test1=0, test2=0, cls=0Java嵌套對象序列化與反序列化
public class Job {private String name;private int salary;public Job(String name, int salary){this.name = name;this.salary = salary;}@Overridepublic String toString(){return "Job{" +"name='" + name + '\'' +", salary = " + salary +'}';} } public void testNestedObject(){User u1 = new User("Lance", "123", 18, false);Job job = new Job("工人", 10000);u1.setJob(job);Gson gson = new Gson();String json = gson.toJson(u1);System.out.println("序列化::" + json);User u2 = gson.fromJson(json, User.class);System.out.println("反序列化::" +u2);}結果:
序列化::{"userName":"Lance","password":"123","age":18,"isStudent":false,"job":{"name":"工人","salary":10000},"test1":0,"class":0} 反序列化::userName=Lance, password=123, age=18, isStudent=false, job=Job{name='工人', salary = 10000}, test1=0, test2=0, cls=02、Array 和 List 的序列化/反序列化
(1)Array數組的序列化與反序列化
數組類型對象和普通對象一樣,使用toJson/fromJson即可完成序列化與返序列化
public void testArray(){User[] users1 = new User[3];users1[0] = new User("Lance", "123", 18, false);users1[1] = new User("Alex", "123", 88, true);Gson gson = new Gson();String json = gson.toJson(users1);System.out.println("序列化:" + json);User[] users2 = gson.fromJson(json, User[].class);System.out.println("反序列化:" + users2[0]);System.out.println("反序列化:" + users2[1]);System.out.println("反序列化:" + users2[2]); }結果:
序列化:[{"userName":"Lance","password":"123","age":18,"isStudent":false,"test1":0,"class":0},{"userName":"Alex","password":"123","age":88,"isStudent":true,"test1":0,"class":0},null] 反序列化:userName=Lance, password=123, age=18, isStudent=false, job=null, test1=0, test2=0, cls=0 反序列化:userName=Alex, password=123, age=88, isStudent=true, job=null, test1=0, test2=0, cls=0 反序列化:null(2)List集合的序列化和反序列化
public void testListObject(){List<User> list1 = new ArrayList<>();list1.add(new User("Lance", "123", 18, false));list1.add(new User("Alex", "123", 88, true));list1.add(null);Gson gson = new Gson();//序列化String json = gson.toJson(list1);System.out.println("List序列化:" + json);//反序列化Type type = new TypeToken<List<User>>(){}.getType();List<User> list2 = gson.fromJson(json, type); //注意,這里是typeSystem.out.println("List反序列化:" + list2.get(0));System.out.println("List反序列化:" + list2.get(1));System.out.println("List反序列化:" + list2.get(2));}結果:
List序列化:[{"userName":"Lance","password":"123","age":18,"isStudent":false,"test1":0,"class":0},{"userName":"Alex","password":"123","age":88,"isStudent":true,"test1":0,"class":0},null] List反序列化:userName=Lance, password=123, age=18, isStudent=false, job=null, test1=0, test2=0, cls=0 List反序列化:userName=Alex, password=123, age=88, isStudent=true, job=null, test1=0, test2=0, cls=0 List反序列化:null注意:
fromJson如果第二個參數為List.class的話,Gson不知道List中的泛型類型是什么,不知道接收數據是哪種類。
TypeToken將泛型指定為List中存儲的類型。
3、Map 和 Set 的序列化/反序列化
(1)Map的序列化與反序列化
Map集合類型對象在反序列化時與List一樣,需要使用TypeToken完成反序列化
public void testMapObject(){Map<String, User> map1 = new HashMap<>();//java對象map1.put("1", new User("Lance","123", 18, false));map1.put("2", new User("Alex","123", 88, true));map1.put("3",null);map1.put(null, null);//Gson提供的Gson對象Gson gson = new Gson();//序列化String json = gson.toJson(map1);System.out.println("Map序列化:" + json);Type type = new TypeToken<Map<String, User>>(){}.getType();Map<String, User> map2 = gson.fromJson(json, type);System.out.println("Map反序列化:" + map2.get(null));System.out.println("Map反序列化:" + map2.get("1"));}結果:
Map序列化:{"1":{"userName":"Lance","password":"123","age":18,"isStudent":false,"test1":0,"class":0},"2":{"userName":"Alex","password":"123","age":88,"isStudent":true,"test1":0,"class":0}} Map反序列化:null Map反序列化:userName=Lance, password=123, age=18, isStudent=false, job=null, test1=0, test2=0, cls=0(2)Set的序列化與反序列化
Set在反序列化時同樣需要使用TypeToken完成反序列化
public void testSetObject(){Set<User> set1 = new HashSet<>();//java對象set1.add( new User("Lance","123", 18, false));set1.add(new User("Alex","123", 88, true));set1.add(null);//Gson提供的Gson對象Gson gson = new Gson();//序列化String json = gson.toJson(set1);System.out.println("Set序列化:" + json);反序列化 // Type type = new TypeToken<List<User>>(){}.getType(); // //如果是 HashSet 類型,則完全可以使用反序列為List,因為ArrayList和HashSet 兩者序列化后的 Json 數據一致。 // List<User> set2 = gson.fromJson(json, type); // System.out.println("Set反序列化:" + set2.get(0)); // System.out.println("Set反序列化:" + set2.get(1)); // System.out.println("Set反序列化:" + set2.get(2));//反序列化Type type = new TypeToken<Set<User>>(){}.getType();//Set需要使用迭代器,不能直接getSet<User> set2 = gson.fromJson(json, type);Iterator<User> iterator = set2.iterator();while(iterator.hasNext()){User next = iterator.next();System.out.println("Set反序列化:" + next);}}結果:
Set序列化:[null,{"userName":"Lance","password":"123","age":18,"isStudent":false,"test1":0,"class":0},{"userName":"Alex","password":"123","age":88,"isStudent":true,"test1":0,"class":0}] Set反序列化:null Set反序列化:userName=Lance, password=123, age=18, isStudent=false, job=null, test1=0, test2=0, cls=0 Set反序列化:userName=Alex, password=123, age=88, isStudent=true, job=null, test1=0, test2=0, cls=04、變量值為null時的序列化/反序列化
(1)如果一個變量為NULL,那么按照 GSON 默認的處理為忽略這個字段
public void testVarNull(){User u1 = new User("Lance", "123", 18, false); //job字段沒有賦值,默認為NULL//Gson提供的Gson對象Gson gson = new Gson();//序列化String json = gson.toJson(u1);System.out.println(json);//反序列化User u2 = gson.fromJson(json, User.class);System.out.println(u2);}結果:
{"userName":"Lance","password":"123","age":18,"isStudent":false,"test1":0,"class":0} userName=Lance, password=123, age=18, isStudent=false, job=null, test1=0, test2=0, cls=0當某個屬性為null時,Gson在序列化時會忽略這個屬性
(2)如果一個集合中的存儲的數據為NULL,那么按照GSON默認的處理為不會忽略
List<User> list1 = new ArrayList<>(); list1.add(new User("Lance", "123", 18, false)); list1.add(null);Gson gson = new Gson();//序列化 String json = gson.toJson(list1); System.out.println("序列化:" + json);結果:
序列化:[{"userName":"Lance","password":"123","age":18,"isStudent":false,"test1":0,"class":0},null]5、控制序列化/反序列化的變量名稱
(1)如果希望JSON字符串字段名不用變量名作為Key(比如User類的userName被作為Key),又或者希望JSON字符串中的Key存在Java中的關鍵字時(如 “class”:18),可以借助 @SerializedName 注解控制 JSON 字段中 Key 的命名。
class User{...@SerializedName("class")private int cls; }(2)如果希望指定GSON對某些字段配置是否參與序列化與反序列化,可以使用 @Expose 注解控制,同時使用 GsonBuilder 創建 Gson 對象。
可以點進去“@Expose”看下源碼,可以發現可以設置變量是否參加 序列化/反序列化
默認情況下,變量是可以參加序列化/反序列化的
要使得 “@Expose” 生效,就不是 new Gson() 了,而是new GsonBuilder().excludeFieldWithoutExposeAnnotation().create();
(3)transient關鍵字的作用:使得變量不參加任何序列化/反序列化
總結
以上是生活随笔為你收集整理的Android基础学习(十五)—— 序列化与反序列化(包括 JSON、GSON))的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 公告栏模板php代码,destoon调用
- 下一篇: Android-Ble蓝牙通讯开发–扫描