該文章翻譯自Gson Tutorial Series系列教程。該篇探究的是如何使用如何使用@Expose忽略某些域以及使用@SerializedName改變域名近顷。
使用@Expose忽略某些域
@Expose注解模型
在閱讀了之前關于處理空值的教程后,你可能會想缤灵,你能夠將一個Java對象設置為空值怠蹂,但如何才能夠使之不出現在JSON中呢?這在你不想傳送你的私有或者敏感數據到網絡上時是必要的搀愧。不用擔心惰聂,Gson提供的@Expose注解能輕松解決這個問題。
@Expose注解是可選擇的并且提供了兩個配置參數:serialize和deserialize咱筛。默認情況下搓幌,它們都設置為true。因此迅箩,你不用強制給每個成員變量添加@Expose注解溉愁,就像我們之前做的,所有成員變量會默認添加饲趋。如果你添加了@Expose注解拐揭,而沒有設置任何值為false撤蟆,該成員變量也會默認包含的。
讓我們重新看一下UserSimple類堂污,然后添加@Expose注解:
public class UserSimple {
@Expose()
String name; // equals serialize & deserialize
@Expose(serialize = false, deserialize = false)
String email; // equals neither serialize nor deserialize
@Expose(serialize = false)
int age; // equals only deserialize
@Expose(deserialize = false)
boolean isDeveloper; // equals only serialize
}
上例中家肯,序列化的結果將只有name和isDeveloper會出現在JSON中。其他兩個域敷鸦,即使它們設置了息楔,也不會轉換。
在反序列化過程中扒披,Java對象將只會擁有JSON中的name和age域值依,email和isDeveloper將會被忽略。
默認情況下碟案,Gson實例會忽略掉@Expose注解愿险。為了使用它,你需要自定義Gson實例:
GsonBuilder builder = new GsonBuilder();
builder.excludeFieldsWithoutExposeAnnotation();
Gson gson = builder.create();
遵循此用法的gson才會注重Expose注解价说。
@Expose注解使得你可以輕松的空值哪些值可以被序列化和反序列化辆亏。建議在需要轉換所有值得情況下不要使用@Expose標簽。它僅僅會毀掉你的模型類鳖目。
Transient
@Expose的替代方法是在定義成員變量時添加transient關鍵字扮叨。添加了該關鍵字的成員變量將不會被轉換。然而领迈,你并不能像@Expose那樣完全掌控彻磁。你不能使一個方向運行而反方向又不能運行,transient將使得該域既不能序列化也不能反序列化狸捅。
public class UserSimple {
String name;
String email;
int age;
boolean transient isDeveloper; // will not be serialized or deserialized
}
使用@SerializedName注解改變域名
@SerializedName注解模型
@SerializedName是一個非常有用的注解衷蜓。它改變了Java-JSON序列化和反序列化過程中的自動匹配。到目前為止尘喝,我們經常假設Java模型類和JSON有相同的“名”磁浇。然而,并不總是如此朽褪≈孟牛可能是你沒有獲得繼承Java模型類的允許,也可能是你必須遵循公司的命名規(guī)則缔赠,無論哪種情況交洗,你都可以使用@SerializedName以使得Gson能夠正確的匹配。
讓我們看個例子橡淑。我們的UserSimple類已經去掉了@Expose,它可以映射所有域了咆爽。
public class UserSimple {
String name;
String email;
boolean isDeveloper;
int age;
}
然而梁棠,讓我們花點時間想象一下置森,API實現以及它所返回的JSON已經改變了。我們的API不再會返回name而是返回了fullName:
{
"age": 26,
"email": "norman@futurestud.io",
"fullName": "Norman",
"isDeveloper": true
}
不用擔心符糊,我們并不需要改變我們的基礎代碼凫海,我們僅僅需要在我們的模型中添加一個簡單的注解:
public class UserSimple {
@SerializedName("fullName")
String name;
String email;
boolean isDeveloper;
int age;
}
在該注解的幫助下,Gson又可以映射良好了男娄,我們又可以享受自動化帶來的好處了行贪。
當然,你可以使用@SerializedName去遵從你們公司的命名規(guī)則模闲,但是依然可以正確匹配任何API建瘫。這在命名規(guī)則非常不同時是有用的。
使用@SerializedName反序列化多個名稱
在之前的博客中尸折,我們已經介紹了如何在序列化和反序列化過程中改變一個模型的屬性名啰脚。如果你的服務器希望接收或者發(fā)送的屬性名是不一樣的,那么你可以使用@SerializedName实夹。
在這篇博客中橄浓,我們將想你展示,如何實現一個屬性對應多個名稱的映射亮航。這在你的應用需要與多個API通信時是非常有用的荸实。盡管這些API使用不同的名稱描述了相同的事情,你依然可以只使用一個Java模型類缴淋。
擴展@SerializedName注解模型
在介紹@SerializedName的第一篇博客中准给,我們向你介紹了如下用法:
public class UserSimple {
@SerializedName("fullName")
String name;
String email;
boolean isDeveloper;
int age;
}
你為該模型的一個屬性添加了一個注解,并且向序列化和反序列化傳遞了一個字符串名宴猾。
但這并不是全部圆存!SerializeName接收兩個參數:value和alternate。前者使用了默認的參數仇哆。如果你僅僅傳入了一個字符串沦辙,那么將該字符串設置給value而alternate設置為空值。但是你可以給這兩個參數傳遞值:
public class UserSimpleSerializedName {
@SerializedName(value = "fullName", alternate = "username")
private String name;
private String email;
private boolean isDeveloper;
private int age;
}
強調一遍讹剔,value改變了序列化和反序列化的默認情況油讯!因此,如果Gson根據你的Java模型類創(chuàng)建了一個JSON延欠,它將會使用value作為該屬性的名陌兑。
alternate僅僅是作為反序列化中的代選項。Gson將會JSON中的所有名稱并且嘗試映射到被注解了的屬性中的某一個由捎。在上面的模型類中兔综,Gson將會檢查到來的JSON中是否含有fullName或者username鸠天。無論是哪一個抽兆,都會映射到name屬性:
{
'fullName': 'Norman',
'email': 'norman@futurestud.io'
}
以及
{
'username': 'Norman',
'email': 'norman@futurestud.io'
}
上面兩個JSON會映射到相同的Java對象。
如果有多個域匹配一個屬性,Gson會使用最后一個遇到的域蹲缠。例如费就,在下面的JSON中咖城,name屬性的值將會設置為Marcus十绑,因為該值來的最晚:
{
'username': 'Norman',
'fullName': 'Marcus',
'email': 'norman@futurestud.io'
}
如果你的服務器創(chuàng)建了自相矛盾的JSON,你將不會知道哪個屬性會被匹配慧瘤。
前瞻
在這篇博客中戴已,我們學習了使用@SerializedName去處理多個名稱對應單個屬性的情況。
記住锅减,這僅僅限于反序列化糖儡。Gson會從多個JSON值映射到你的Java對象,但往往會創(chuàng)建在序列化過程中創(chuàng)建相同的JSON上煤。