java对象常用的跨语言序列化反序列化主要有三种:一是xml形式;二是json形式;三是protobuf字节流形式。本篇文章主要介绍这三种序列化反序列化方式的实现和其效率对比。
首先介绍xml形式的序列化与反序列化,使用jaxb来实现。JAXB能够使用Jackson对JAXB注解的支持实现(jackson-module-jaxb-annotations),既方便生成XML,也方便生成JSON,这样一来可以更好的标志可以转换为JSON对象的JAVA类。JAXB允许JAVA人员将JAVA类映射为XML表示方式,常用的注解包括:@XmlRootElement,@XmlElement等等。其maven依赖为:
<!-- http://mvnrepository.com/artifact/com.sun.xml.bind/jaxb-core -->
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-core</artifactId>
<version>2.2.11</version>
</dependency>
<!-- http://mvnrepository.com/artifact/javax.xml/jaxb-api -->
<dependency>
<groupId>javax.xml</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.1</version>
</dependency>
<!-- http://mvnrepository.com/artifact/com.sun.xml.bind/jaxb-impl -->
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.2.11</version>
</dependency>
定义的pojo类有两个:第一个是Book.java,另一个为BookList.java,是Book的集合类。只需要在定义的类名上添加@XmlRootElement注解即可,对业务代码没有侵入性。其中两个类中的属性值上有@Protobuf注解,这是protobuf序列化需要的,对xml序列化无影响。
Book类代码:
package zhangq.pojo;
import javax.xml.bind.annotation.XmlRootElement;
import com.baidu.bjf.remoting.protobuf.FieldType;
import com.baidu.bjf.remoting.protobuf.annotation.Protobuf;
@XmlRootElement
public class Book {
@Protobuf(fieldType = FieldType.INT32, order=1)
int id;
@Protobuf(fieldType = FieldType.STRING, order=2)
String name;
@Protobuf(fieldType = FieldType.STRING, order=3)
String address;
@Protobuf(fieldType = FieldType.STRING, order=4)
String buyer;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getBuyer() {
return buyer;
}
public void setBuyer(String buyer) {
this.buyer = buyer;
}
@Override
public String toString() {
return "Book [id=" + id + ", name=" + name + ", address=" + address + ", buyer=" + buyer + "]";
}
}
BookList类代码:
package zhangq.pojo;
import java.util.List;
import javax.xml.bind.annotation.XmlRootElement;
import com.baidu.bjf.remoting.protobuf.annotation.Protobuf;
@XmlRootElement
public class BookList{
@Protobuf(order=1)
private List<Book> books;
public List<Book> getBooks() {
return books;
}
public void setBooks(List<Book> books) {
this.books = books;
}
@Override
public String toString() {
return "BookList [books=" + books + "]";
}
}
定义完pojo后,就可以进行xml的序列化与反序列化实现了。
首先定义一个测试辅助类,用来生成pojo实例:
package zhangq.test;
import java.util.ArrayList;
import java.util.List;
import zhangq.pojo.Book;
import zhangq.pojo.BookList;
public class TestHelper {
public static BookList buildBookList(int count){
BookList bookList = new BookList();
List<Book> books = new ArrayList<Book>();
for (int i=0; i<count; i++){
books.add(buildBook(i));
}
bookList.setBooks(books);
return bookList;
}
public static Book buildBook(int id){
Book book = new Book();
book.setAddress("Peking");
book.setBuyer("hello");
book.setId(id);
book.setName("Netty");
return book;
}
}
然后,定义一个性能记录类,用来记录序列化与反序列化的耗时:
package zhangq.util;
import org.apache.log4j.Logger;
public class PerformanceRecord {
private static Logger m_Logger = Logger.getLogger(PerformanceRecord.class);
private String desp;
private long iStart;
private PerformanceRecord(String desp){
this.desp = desp;
}
public static PerformanceRecord getInstance(String desp){
return new PerformanceRecord(desp);
}
public long start(){
iStart = System.nanoTime();
return iStart;
}
public double endInSeconds(){
long iEnd = System.nanoTime();
double timeInSeconds = (iEnd - iStart) / (1000000000.0);
m_Logger.info(desp + " 耗时为 [" + timeInSeconds + "] 秒");
return timeInSeconds;
}
public double endInMs(){
long iEnd = System.nanoTime();
double timeInMs = (iEnd - iStart) / (1000000.0);
m_Logger.info(desp + " 耗时为 [" + timeInMs + "] 毫秒");
return timeInMs;
}
public long endInNs(){
long iEnd = System.nanoTime();
long timeInNs = (iEnd - iStart);
m_Logger.info(desp + " 耗时为 [" + timeInNs + "] 纳秒");
return timeInNs;
}
}
使用jaxb进行xml序列化的代码为:
public static String testMarshallList(int count) throws Exception{
BookList books = TestHelper.buildBookList(count);
JAXBContext jaxbContext = JAXBContext.newInstance(BookList.class);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
OutputStream outputStream = new ByteArrayOutputStream();
PerformanceRecord performanceRecord = PerformanceRecord.getInstance("XmlMashall");
performanceRecord.start();
marshaller.marshal(books, outputStream);
performanceRecord.endInMs();
String string = outputStream.toString();
outputStream.close();
//m_Logger.debug("ObjToXml:");
//m_Logger.debug(string);
return string;
}
使用jaxb进行xml反序列化的代码为:
public static BookList testUnMarshallList(String string) throws Exception{
JAXBContext jaxbContext = JAXBContext.newInstance(BookList.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
InputStream inputStream = new ByteArrayInputStream(string.getBytes());
PerformanceRecord performanceRecord = PerformanceRecord.getInstance("XmlUnmashall");
performanceRecord.start();
BookList books = (BookList)unmarshaller.unmarshal(inputStream);
performanceRecord.endInMs();
//m_Logger.debug("XmlToObj:");
//m_Logger.debug(books.toString());
return books;
}
其次介绍json的序列化,使用jackson实现。使用jackson,不需要对pojo进行任何修改,不需要添加注解。其maven依赖为:
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.5</version>
</dependency>
jackson的json序列化代码为:
public static String testObjToJsonList(int count) throws Exception{
String string = null;
BookList books = TestHelper.buildBookList(count);
ObjectMapper mapper = new ObjectMapper();
PerformanceRecord performanceRecord = PerformanceRecord.getInstance("Jsonmashall");
performanceRecord.start();
string = mapper.writeValueAsString(books);
performanceRecord.endInMs();
// m_Logger.debug("ObjToJson:");
// m_Logger.debug(string);
return string;
}
jackson的json反序列化代码为:
public static BookList testJsonToObjList(String string) throws Exception{
BookList books = null;
ObjectMapper mapper = new ObjectMapper();
PerformanceRecord performanceRecord = PerformanceRecord.getInstance("JsonUnmashall");
performanceRecord.start();
books = mapper.readValue(string, BookList.class);
performanceRecord.endInMs();
// m_Logger.debug("JsonToObj:");
// m_Logger.debug(books.toString());
return books;
}
<!-- https://mvnrepository.com/artifact/com.baidu/jprotobuf -->
<dependency>
<groupId>com.baidu</groupId>
<artifactId>jprotobuf</artifactId>
<version>2.1.8</version>
</dependency>
jprotobuf序列化代码为:
public static byte[] testObjToByteList(int count){
Codec<BookList> simpleTypeCodec = ProtobufProxy
.create(BookList.class);
BookList books = TestHelper.buildBookList(count);
byte[] bytes = null;
try {
PerformanceRecord performanceRecord = PerformanceRecord.getInstance("ProtoBufMashall:");
performanceRecord.start();
bytes = simpleTypeCodec.encode(books);
performanceRecord.endInMs();
} catch (IOException e) {
// TODO Auto-generated catch block
m_Logger.error(e.toString());
}
return bytes;
}
jprotobuf反序列化代码为:
public static BookList testByteToObjList(byte[] bytes){
Codec<BookList> simpleTypeCodec = ProtobufProxy
.create(BookList.class);
BookList books = null;
try{
PerformanceRecord performanceRecord = PerformanceRecord.getInstance("ProtoBufUnMashall:");
performanceRecord.start();
books = simpleTypeCodec.decode(bytes);
performanceRecord.endInMs();
}catch (Exception e){
m_Logger.error(e.toString());
}
return books;
}
最后,需要对这三种方式的序列化与反序列化耗时进行记录,并对其序列化后的字节大小进行比较。需要注意的是,这三种方式都会涉及到预处理,并且内部有缓存等优化机制,因此对每种的序列化与反序列化函数运行两次,取第二次的耗时,这更符合实际工程运行时的耗时。
其中横轴代表Book实例的个数,纵轴表示耗时,单位毫秒。
下面是反序列化耗时:
其中横轴代表Book实例的个数,纵轴表示耗时,单位毫秒。
横轴是Book实例个数,纵轴是字节个数,单位个。
根据图表分析,jprotobuf进行序列化时,耗时最长,但是反序列化耗时最短、序列化字节长度最短。xml/jaxb反序列化耗时最长,序列化字节长度最长。json/jackson表现较为适中。
今天的文章java实现序列化和反序列化_Java对象序列化和反序列化分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/88965.html