該文章翻譯自Gson Tutorial Series系列教程。該篇探究的是如何使用如何使用@Expose忽略某些域以及使用@SerializedName改變域名。
使用@Expose忽略某些域
@Expose注解模型
在閱讀了之前關(guān)于處理空值的教程后,你可能會(huì)想,你能夠?qū)⒁粋€(gè)Java對(duì)象設(shè)置為空值,但如何才能夠使之不出現(xiàn)在JSON中呢?這在你不想傳送你的私有或者敏感數(shù)據(jù)到網(wǎng)絡(luò)上時(shí)是必要的。不用擔(dān)心,Gson提供的@Expose注解能輕松解決這個(gè)問題。
@Expose注解是可選擇的并且提供了兩個(gè)配置參數(shù):serialize和deserialize。默認(rèn)情況下,它們都設(shè)置為true。因此,你不用強(qiáng)制給每個(gè)成員變量添加@Expose注解,就像我們之前做的,所有成員變量會(huì)默認(rèn)添加。如果你添加了@Expose注解,而沒有設(shè)置任何值為false,該成員變量也會(huì)默認(rèn)包含的。
讓我們重新看一下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
}
上例中,序列化的結(jié)果將只有name和isDeveloper會(huì)出現(xiàn)在JSON中。其他兩個(gè)域,即使它們設(shè)置了,也不會(huì)轉(zhuǎn)換。
在反序列化過程中,Java對(duì)象將只會(huì)擁有JSON中的name和age域,email和isDeveloper將會(huì)被忽略。
默認(rèn)情況下,Gson實(shí)例會(huì)忽略掉@Expose注解。為了使用它,你需要自定義Gson實(shí)例:
GsonBuilder builder = new GsonBuilder();
builder.excludeFieldsWithoutExposeAnnotation();
Gson gson = builder.create();
遵循此用法的gson才會(huì)注重Expose注解。
@Expose注解使得你可以輕松的空值哪些值可以被序列化和反序列化。建議在需要轉(zhuǎn)換所有值得情況下不要使用@Expose標(biāo)簽。它僅僅會(huì)毀掉你的模型類。
Transient
@Expose的替代方法是在定義成員變量時(shí)添加transient關(guān)鍵字。添加了該關(guān)鍵字的成員變量將不會(huì)被轉(zhuǎn)換。然而,你并不能像@Expose那樣完全掌控。你不能使一個(gè)方向運(yùn)行而反方向又不能運(yùn)行,transient將使得該域既不能序列化也不能反序列化。
public class UserSimple {
String name;
String email;
int age;
boolean transient isDeveloper; // will not be serialized or deserialized
}
使用@SerializedName注解改變域名
@SerializedName注解模型
@SerializedName是一個(gè)非常有用的注解。它改變了Java-JSON序列化和反序列化過程中的自動(dòng)匹配。到目前為止,我們經(jīng)常假設(shè)Java模型類和JSON有相同的“名”。然而,并不總是如此??赡苁悄銢]有獲得繼承Java模型類的允許,也可能是你必須遵循公司的命名規(guī)則,無論哪種情況,你都可以使用@SerializedName以使得Gson能夠正確的匹配。
讓我們看個(gè)例子。我們的UserSimple類已經(jīng)去掉了@Expose,它可以映射所有域了。
public class UserSimple {
String name;
String email;
boolean isDeveloper;
int age;
}
然而,讓我們花點(diǎn)時(shí)間想象一下,API實(shí)現(xiàn)以及它所返回的JSON已經(jīng)改變了。我們的API不再會(huì)返回name而是返回了fullName:
{
"age": 26,
"email": "norman@futurestud.io",
"fullName": "Norman",
"isDeveloper": true
}
不用擔(dān)心,我們并不需要改變我們的基礎(chǔ)代碼,我們僅僅需要在我們的模型中添加一個(gè)簡單的注解:
public class UserSimple {
@SerializedName("fullName")
String name;
String email;
boolean isDeveloper;
int age;
}
在該注解的幫助下,Gson又可以映射良好了,我們又可以享受自動(dòng)化帶來的好處了。
當(dāng)然,你可以使用@SerializedName去遵從你們公司的命名規(guī)則,但是依然可以正確匹配任何API。這在命名規(guī)則非常不同時(shí)是有用的。
使用@SerializedName反序列化多個(gè)名稱
在之前的博客中,我們已經(jīng)介紹了如何在序列化和反序列化過程中改變一個(gè)模型的屬性名。如果你的服務(wù)器希望接收或者發(fā)送的屬性名是不一樣的,那么你可以使用@SerializedName。
在這篇博客中,我們將想你展示,如何實(shí)現(xiàn)一個(gè)屬性對(duì)應(yīng)多個(gè)名稱的映射。這在你的應(yīng)用需要與多個(gè)API通信時(shí)是非常有用的。盡管這些API使用不同的名稱描述了相同的事情,你依然可以只使用一個(gè)Java模型類。
擴(kuò)展@SerializedName注解模型
在介紹@SerializedName的第一篇博客中,我們向你介紹了如下用法:
public class UserSimple {
@SerializedName("fullName")
String name;
String email;
boolean isDeveloper;
int age;
}
你為該模型的一個(gè)屬性添加了一個(gè)注解,并且向序列化和反序列化傳遞了一個(gè)字符串名。
但這并不是全部!SerializeName接收兩個(gè)參數(shù):value和alternate。前者使用了默認(rèn)的參數(shù)。如果你僅僅傳入了一個(gè)字符串,那么將該字符串設(shè)置給value而alternate設(shè)置為空值。但是你可以給這兩個(gè)參數(shù)傳遞值:
public class UserSimpleSerializedName {
@SerializedName(value = "fullName", alternate = "username")
private String name;
private String email;
private boolean isDeveloper;
private int age;
}
強(qiáng)調(diào)一遍,value改變了序列化和反序列化的默認(rèn)情況!因此,如果Gson根據(jù)你的Java模型類創(chuàng)建了一個(gè)JSON,它將會(huì)使用value作為該屬性的名。
alternate僅僅是作為反序列化中的代選項(xiàng)。Gson將會(huì)JSON中的所有名稱并且嘗試映射到被注解了的屬性中的某一個(gè)。在上面的模型類中,Gson將會(huì)檢查到來的JSON中是否含有fullName或者username。無論是哪一個(gè),都會(huì)映射到name屬性:
{
'fullName': 'Norman',
'email': 'norman@futurestud.io'
}
以及
{
'username': 'Norman',
'email': 'norman@futurestud.io'
}
上面兩個(gè)JSON會(huì)映射到相同的Java對(duì)象。
如果有多個(gè)域匹配一個(gè)屬性,Gson會(huì)使用最后一個(gè)遇到的域。例如,在下面的JSON中,name屬性的值將會(huì)設(shè)置為Marcus,因?yàn)樵撝祦淼淖钔恚?/p>
{
'username': 'Norman',
'fullName': 'Marcus',
'email': 'norman@futurestud.io'
}
如果你的服務(wù)器創(chuàng)建了自相矛盾的JSON,你將不會(huì)知道哪個(gè)屬性會(huì)被匹配。
前瞻
在這篇博客中,我們學(xué)習(xí)了使用@SerializedName去處理多個(gè)名稱對(duì)應(yīng)單個(gè)屬性的情況。
記住,這僅僅限于反序列化。Gson會(huì)從多個(gè)JSON值映射到你的Java對(duì)象,但往往會(huì)創(chuàng)建在序列化過程中創(chuàng)建相同的JSON。