浅析若干Java序列化工具
生活随笔
收集整理的這篇文章主要介紹了
浅析若干Java序列化工具
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
在java中socket傳輸數(shù)據(jù)時,數(shù)據(jù)類型往往比較難選擇。可能要考慮帶寬、跨語言、版本的兼容等問題。
比較常見的做法有:1. 采用java對象的序列化和反序列化2. 把對象包裝成JSON字符串傳輸3. Google工具protoBuf的開源對UserVo對象進行序列化,class UserVo如下:
package com.serialize;import java.io.Serializable;
import java.util.List;public class UserVo implements Serializable {private static final long serialVersionUID = -8647002929026226508L;private String name;private int age;private List<UserVo> friends;public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public List<UserVo> getFriends() {return friends;}public void setFriends(List<UserVo> friends) {this.friends = friends;}@Overridepublic String toString() {return "UserVo [name=" + name + ", age=" + age + ", friends=" + friends + "]";}}
package com.serialize;import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;public class MainTest {public static void main(String[] args) throws IOException {UserVo user = new UserVo();user.setName("zzh");user.setAge(18);UserVo f1 = new UserVo();f1.setName("jj");f1.setAge(17);UserVo f2 = new UserVo();f2.setName("qq");f2.setAge(19);List<UserVo> friends = new ArrayList<UserVo>();friends.add(f1);friends.add(f2);user.setFriends(friends);ByteArrayOutputStream os = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(os);oos.writeObject(user);oos.flush();oos.close();System.out.println(os.toByteArray().length);}}
序列化大小:200優(yōu)點:java原生支持,不需要提供第三方的類庫,使用比較簡單。缺點:無法跨語言,字節(jié)數(shù)占用比較大,某些情況下對于對象屬性的變化比較敏感。
##把對象包裝成JSON字符串傳輸JSON工具類有許多種,這里列出三個比較流行的json工具類:Jackson,Gson,FastJson.###1.開源的JacksonJackson社區(qū)相對比較活躍,更新速度也比較快。Jackson對于復雜類型的json轉(zhuǎn)換bean會出現(xiàn)問題,一些集合Map,List的轉(zhuǎn)換出現(xiàn)問題。Jackson對于復雜類型的bean轉(zhuǎn)換Json,轉(zhuǎn)換的json格式不是標準的Json格式。
package com.test.serialize;import java.io.IOException;
import java.util.ArrayList;
import java.util.List;import org.junit.After;
import org.junit.Before;
import org.junit.Test;import com.aztech.test.serialize.UserVo;
import com.fasterxml.jackson.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.ObjectMapper;public class JacksonTest {private UserVo user = null;private JsonGenerator jsonGenerator;private ObjectMapper objectMapper = null;@Beforepublic void init() {user = new UserVo();user.setName("zzh");user.setAge(18);UserVo f1 = new UserVo();f1.setName("jj");f1.setAge(17);UserVo f2 = new UserVo();f2.setName("qq");f2.setAge(19);List<UserVo> friends = new ArrayList<UserVo>();friends.add(f1);friends.add(f2);user.setFriends(friends);objectMapper = new ObjectMapper();try {jsonGenerator = objectMapper.getJsonFactory().createJsonGenerator(System.out,JsonEncoding.UTF8);} catch (IOException e) {e.printStackTrace();}}@Afterpublic void destory() {try {if(jsonGenerator!=null) {jsonGenerator.flush();}if(!jsonGenerator.isClosed()) {jsonGenerator.close();}jsonGenerator = null;objectMapper = null;user = null;} catch (Exception e) {e.printStackTrace();}}@Testpublic void writeJson() {try {jsonGenerator.writeObject(user);System.out.println();System.out.println(objectMapper.writeValueAsBytes(user).length);} catch (IOException e) {e.printStackTrace();}}@Testpublic void readJson() {String serString = "{\"name\":\"zzh\",\"age\":18,\"friends\":[{\"name\":\"jj\",\"age\":17,\"friends\":null},{\"name\":\"qq\",\"age\":19,\"friends\":null}]}";UserVo userVo = null;try {userVo = objectMapper.readValue(serString, UserVo.class);} catch (IOException e) {e.printStackTrace();}System.out.println(userVo.getName()); }
}
{"name":"zzh","age":18,"friends":[{"name":"jj","age":17,"friends":null},
{"name":"qq","age":19,"friends":null}]}
111
序列化大小:111.注意到這里Jackson會輸出null,在Jackson的2.x版本中可以通過設置而使其不輸出null的字段。
###2. Google的GsonGson是目前功能最全的Json解析神器,Gson當初是為因應Google公司內(nèi)部需求而由Google自行研發(fā)而來,但自從在2008年五月公開發(fā)布第一版后已被許多公司或用戶應用。Gson的應用主要為toJson與fromJson兩個轉(zhuǎn)換函數(shù),無依賴,不需要例外額外的jar,能夠直接跑在JDK上。而在使用這種對象轉(zhuǎn)換之前需先創(chuàng)建好對象的類型以及其成員才能成功的將JSON字符串成功轉(zhuǎn)換成相對應的對象。類里面只要有get和set方法,Gson完全可以將復雜類型的json到bean或bean到json的轉(zhuǎn)換,是JSON解析的神器。Gson在功能上面無可挑剔,但是性能上面比FastJson有所差距。
package com.aztech.test.serialize;import java.util.ArrayList;
import java.util.List;import org.junit.Before;
import org.junit.Test;import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;public class GsonTest {private UserVo user = null;@Beforepublic void init() {user = new UserVo();user.setName("zzh");user.setAge(18);UserVo f1 = new UserVo();f1.setName("jj");f1.setAge(17);UserVo f2 = new UserVo();f2.setName("qq");f2.setAge(19);List<UserVo> friends = new ArrayList<UserVo>();friends.add(f1);friends.add(f2);user.setFriends(friends); }@Testpublic void writeJson() {try {String str = Gson.class.newInstance().toJson(user);System.out.println(str);System.out.println(str.length());} catch (InstantiationException | IllegalAccessException e) {e.printStackTrace();} }@Testpublic void readJson() {String serString = "{\"name\":\"zzh\",\"age\":18,\"friends\":[{\"name\":\"jj\",\"age\":17},{\"name\":\"qq\",\"age\":19}]}";try {UserVo userVo = Gson.class.newInstance().fromJson(serString, UserVo.class);System.out.println(userVo.getName());} catch (JsonSyntaxException | InstantiationException | IllegalAccessException e) {e.printStackTrace();}}
}
{"name":"zzh","age":18,"friends":[{"name":"jj","age":17},{"name":"qq","age":19}]}
81
Gson和Jackson的區(qū)別是:如果你的應用經(jīng)常會處理大的JSON文件,那么Jackson應該是你的菜。GSON在大文件上表現(xiàn)得相當吃力。如果你主要是處理小文件請求,比如某個微服務或者分布式架構(gòu)的初始化,那么GSON當是首選。Jackson在小文件上的表現(xiàn)則不如人意。
###3. 阿里巴巴的FastJsonFastjson是一個Java語言編寫的高性能的JSON處理器,由阿里巴巴公司開發(fā)。無依賴,不需要例外額外的jar,能
夠直接跑在JDK上。
FastJson在復雜類型的Bean轉(zhuǎn)換Json上會出現(xiàn)一些問題,可能會出現(xiàn)引用的類型,導致Json轉(zhuǎn)換出錯,需要制定
引用。FastJson采用獨創(chuàng)的算法,將parse的速度提升到極致,超過所有json庫。
package com.aztech.test.serialize;import java.util.ArrayList;
import java.util.List;import org.junit.Before;
import org.junit.Test;import com.alibaba.fastjson.JSON;public class FastJsonTest {private UserVo user = null;@Beforepublic void init() {user = new UserVo();user.setName("zzh");user.setAge(18);UserVo f1 = new UserVo();f1.setName("jj");f1.setAge(17);UserVo f2 = new UserVo();f2.setName("qq");f2.setAge(19);List<UserVo> friends = new ArrayList<UserVo>();friends.add(f1);friends.add(f2);user.setFriends(friends); }@Testpublic void writeJson() {String str = JSON.toJSONString(user);System.out.println(str);System.out.println(str.length());}@Testpublic void readJson() {String serString = "{\"name\":\"zzh\",\"age\":18,\"friends\":[{\"name\":\"jj\",\"age\":17},{\"name\":\"qq\",\"age\":19}]}";UserVo userVo = JSON.parseObject(serString,UserVo.class);System.out.println(userVo.getName());}
}
{"age":18,"friends":[{"age":17,"name":"jj"},{"age":19,"name":"qq"}],"name":"zzh"}
81zzh
注:如果只是功能要求,沒有性能要求,可以使用google的Gson,如果有性能上面的要求可以使用Gson將bean轉(zhuǎn)換json確保數(shù)據(jù)的正確,使用FastJson將Json轉(zhuǎn)換Bean。
##Google工具protoBufprotocol buffers 是google內(nèi)部得一種傳輸協(xié)議,目前項目已經(jīng)開源。它定義了一種緊湊得可擴展得二進制協(xié)議格式,適合網(wǎng)絡傳輸,并且針對多個語言有不同得版本可供選擇。protoBuf優(yōu)點:1. 性能好,效率高;2. 代碼生成機制,數(shù)據(jù)解析類自動生成;3. 支持向前兼容和向后兼容;4. 支持多種編程語言;5. 字節(jié)數(shù)很小,適合網(wǎng)絡傳輸節(jié)省io。缺點:1.應用不夠廣;2.二進制格式導致可讀性差;3.缺乏自描述;protoBuf是需要編譯工具的,這里用的是window的系統(tǒng)。需要下載proto.exe和protobuf-java-2.4.1.jar;
注:protobuf的一個缺點是需要數(shù)據(jù)結(jié)構(gòu)的預編譯過程,首先要編寫.proto格式的配置文件,再通過protobuf提供的工具生成各種語言響應的代碼。由于java具有反射和動態(tài)代碼生成的能力,這個預編譯過程不是必須的,可以在代碼執(zhí)行時來實現(xiàn)。protostuff(http://code.google.com/p/protostuff/)已經(jīng)實現(xiàn)了這個功能。protostuff基于Google protobuf,但是提供了更多的功能和更簡易的用法。其中,protostuff-runtime實現(xiàn)了無需預編譯對java bean進行protobuf序列化/反序列化的能力。protostuff-runtime的局限是序列化前需預先傳入schema,反序列化不負責對象的創(chuàng)建只負責復制,因而必須提供默認構(gòu)造函數(shù)。此外,protostuff還可以按照protobuf的配置序列化成json/yaml/xml等格式。這里不做詳述,有興趣的朋友可以參考相關資料。
?
| 方式 | 優(yōu)點 | 缺點 | |
| JSON |
| 字節(jié)數(shù)比較大,需要第三方類庫 | |
| Object Serialize | java原生方法不依賴外部類庫 | 字節(jié)數(shù)大,不能跨語言 | |
| Google protobuf | 跨語言、字節(jié)數(shù)比較少 | 編寫.proto配置用protoc工具生成對應的代碼 |
?
總結(jié)
以上是生活随笔為你收集整理的浅析若干Java序列化工具的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 设计模式之_Iterator_01
- 下一篇: Java语法糖之foreach