使用jackson進行序列化時,往往會遇到后台某個實體對象的屬性為null,當序列化成json時對應的屬性也為null,可以用以下的注解方式完成當屬性為null時不參與序列化:
@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
@JsonIgnoreProperties
類注解,作用是json序列化時將bean中的一些屬性忽略掉,序列化和反序列化都受影響。
@JsonIgnore
作用於屬性或字段上,當生成json時忽略有該annotation的方法或字段。
@JsonProperty("rename")
作用於屬性或字段上,對其重命名。
@JsonFormat
作用於屬性或字段上,方便把Date類型直接轉化為我們想要的模式,如@JsonFormat(pattern="yyyy-MM-dd HH-mm-ss")
@JsonSerialize
作用於屬性或字段上,指定序列化方式。
例如:@JsonSerialize(as=BasicType.class)將類型序列化成指定類型;@JsonSerialize(using=CustomDoubleSerialize.class)用於在序列化時嵌入我們自定義的代碼,比如序列化一個double時在其后限制兩位小數。
@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) //保證序列化json的時候,如果是null的對象,key也會消失 //比如在創建失敗的時候,只需要將status和msg顯示出來,但是如果不加上面的注解會將data也顯示出來,其值會顯示null
@JsonDeserialize
作用於屬性或字段上,指定反序列化方式。
例如:@JsonDeserialize(as=ValueImpl.class)將類型反序列化成指定類型;@JsonDeserialize(using=CustomDateDeserialize.class)用於在反序列化時嵌入我們自定義的代碼。
序列化與反序列化
例子:
public class ServerResponse<T> implements Serializable{
Serializable是一個標識接口,它沒有定義任何方法,實現了這個接口,就代表這個類可以進行串行化了。
串行化也叫序列化,就是將實例的狀態轉化成文本(或二進制)的形式,以便永久保存(所以也叫持久化)或在網間傳遞。
什么時候實現java.io.Serializable接口?
如果一個類的實例需要持久化或者需要在網間傳遞的時候,就用到串行化。
例如:action,dao層的一些個類一般不需要串行化,而bean層的一些個類一般需要串行化。因為客戶端用到action,dao層的時候都是import過來,然后自己進行實例化的,或者直接調用容器中的實例;而bean不一樣,客戶端不可以new一個出來給自己,客戶端需要從服務器端接收一個bean,讀取bean中的信息狀態,然后做出一系列反應,而這個傳輸過程就用到了串行化。
為什么要實現序列化?
序列化實體對象是為了方便網絡傳輸。因為網絡傳輸數據只能是二進制流,序列化能將實體轉化為二進制流傳輸,同時還可通過反序列化重新將二進制流還原成實體對象。
序列化在網絡協議中的應用:
OSI七層協議模型中表現層的主要功能是把應用層的對象轉換成一段連續的二進制串,或者反過來,把二進制串轉換成應用層的對象。這兩個功能就是序列化和反序列化。而TCP/IP協議的應用層對應OSI七層模型的應用層、表示層和會話層,所以序列化協議屬於TCP/IP協議應用層的一部分。
序列化:將數據結構或對象轉換成二進制串的過程。
反序列化:將在序列化過程中所生成的二進制串轉換成數據結構或對象的過程。
序列化的作用:
1)把對象的字節序列持久化永久地保存到硬盤上。
例如:web服務器中的session對象,當有10萬用戶並發訪問,就有可能出現10萬個session對象,內存可能不夠用,於是web容器就會把一些session先序列化到硬盤中,等要用的時候,再把保存在硬盤中的對象還原到內存中。
2)在網絡上傳送對象的字節序列。
例如:當兩個進程在進行遠程通信時,彼此可以發送各種類型的數據,無論是何種類型的數據,都會以二進制序列的形式在網絡上傳送,發送方需要把這個java對象轉換為字節序列,才能在網絡上傳送,接收方則需要把字節序列再恢復為java對象。
JDK類庫中的序列化API例子可以詳見http://blog.csdn.net/abc6368765/article/details/51365838
serialVersionUID:序列化的版本號,凡是實現Serializable接口的類都有一個表示序列化版本標識符的靜態變量,即private static final long serialVersionUID。
如何序列化生成serialVersionUID以及是否加這個UID導致的區別和為什么,詳見http://blog.csdn.net/abc6368765/article/details/51365838
最好顯示指定serialVersionUID,為什么?
因為原則上序列化后的數據中的serialVersionUID只有和當前類的serialVersionUID相同時才能被正常的反序列化。如果不顯示指定,在一次執行序列化后,如果增加或者刪除了某些成員變量,再次執行序列化,系統就會重新生成hash值然后賦給UID,導致反序列化的時候報error。
注意:
1.如果一個類想被序列化,需要實現Serializable接口。否則將拋出NotSerializableException
異常,這是因為,在序列化操作過程中會對類型進行檢查,要求被序列化的類必須屬於Enum、Array和Serializable類型其中的任何一種,這也是為什么Serializable雖然是一個空接口,但是只要實現了該接口就能序列化和反序列化。
2.在類中增加writeObject 和 readObject 方法可以實現自定義序列化策略,雖然這倆方法不是被顯示調用,但是因為在使用ObjectOutputStream的writeObject方法和ObjectInputStream的readObject方法時,會通過反射的方式調用到它們。
ArrayList源碼中有關序列化的使用http://www.hollischuang.com/archives/1140#What%20Serializable%20Did