Gson @Expose 和 @SerializedName 之間的區別
1. 概述
在本教程中,我們將了解Gson庫的@Expose
和@SerializedName
註解。 @Expose
幫助控制哪些類屬性可以序列化或反序列化,而**@SerializedName
幫助在序列化和反序列化時將對象的屬性名稱映射到 JSON 字符串中的屬性鍵名稱,反之亦然**。
2. @Expose
在某些用例中,類中屬性的某些敏感值不應序列化或轉換為 JSON 字符串。為了解決這個問題, Gson使用了@Expose
註釋,它有兩個Boolean
屬性: serialize
和deserialize
。
假設Person
類中的屬性password
不應序列化,因為它是敏感信息。因此,我們必須使用註釋@Expose(serialize=false)
來修飾password
屬性:
public class Person {
@Expose(serialize = true)
private String firstName;
@Expose(serialize = true)
private String lastName;
@Expose()
private String emailAddress;
@Expose(serialize = false)
private String password;
@Expose(serialize = true)
private List<BankAccount> bankAccounts;
//General getters and setters..
}
同樣, BankAccount
對像中的accountNumber
不得序列化,因為它也是敏感信息。因此,我們還必須使用註釋@Expose(serialize=false)
來修飾accountNumber
屬性:
public class BankAccount {
@Expose(serialize = false, deserialize = false)
private String accountNumber;
@Expose(serialize = true, deserialize = true)
private String bankName;
//general getters and setters..
}
現在,要將對象轉換為 JSON 字符串,我們不能使用默認的Gson
對象,該對像是通過new
運算符創建的。我們必須使用GsonBuilder
類通過配置excludeFieldsWithoutExposeAnnotation()
設置來實例化Gson
類。
我們看一下PersonSerializer
類:
public class PersonSerializer {
private static final Gson configuredGson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
private static final Gson defaultGson = new Gson();
public static String serializeWithConfiguredGson(Person person) {
return configuredGson.toJson(person);
}
public static String serializeWithDefaultGson(Person person) {
return defaultGson.toJson(person);
}
}
讓我們測試一下方法serializeWithConfiguredGson()
:
public class PersonSerializerUnitTest {
@Test
public void whenUseCustomGson_thenDonotSerializeAccountNumAndPassword () {
String personJson = PersonSerializer.serializeWithConfiguredGson(person);
assertFalse("Test failed: password found", personJson.contains("password"));
assertFalse("Test failed: account number found", personJson.contains("accountNumber:"));
}
}
正如預期的那樣,我們在輸出中沒有看到password
和accountNumber
等敏感屬性:
{
"firstName":"Parthiv",
"lastName":"Pradhan","email":"[email protected]",
"bankAccounts":[{"bankName":"Bank of America"},{"bankName":"Bank of America"}]
}
同樣,讓我們測試方法serializeWithDefaultGson()
:
@Test
public void whenUseDefaultGson_thenSerializeAccountNumAndPassword () {
String personJson = PersonSerializer.serializeWithDefaultGson(person);
assertTrue("Test failed: password not found", personJson.contains("password"));
assertTrue("Test failed: account number not found", personJson.contains("accountNumber"));
}
如前所述, defaultGson
對象無法識別@Expose
註釋,並且如預期的那樣,輸出打印出password
和accountNumber
:
{
"firstName":"James","lastName":"Cameron","email":"[email protected]",
"password":"secret",
"bankAccounts":
[
{"accountNumber":"4565432312","bankName":"Bank of America"},
{"accountNumber":"4565432616","bankName":"Bank of America"}
]
}
要從更高級用例的序列化中排除屬性,我們可以使用ExclusionStrategy
。
3. @SerializedName
@SerializedName
註釋的作用有點像自定義轉換器。通常,我們首先將對象轉換為 JSON 字符串,然後修改其屬性鍵,然後將其作為參數發送到 Web 服務。
同樣,在將 JSON 字符串轉換為對象時,我們必須將其屬性鍵映射到對象的屬性名稱。 Gson 庫借助一個註釋[@SerializedName](https://www.javadoc.io/doc/com.google.code.gson/gson/latest/com.google.gson/com/google/gson/annotations/SerializedName.html) .
多麼簡單啊!
通常,當我們序列化時,我們希望生成盡可能小的有效負載。讓我們嘗試使用一些比屬性名稱短得多的自定義鍵名稱來序列化以下Country c
類:
public class Country {
@SerializedName(value = "name")
private String countryName;
@SerializedName(value = "capital")
private String countryCapital;
@SerializedName(value = "continent")
private String continentName;
//general getters and setters..
}
現在,讓我們將Country
對象轉換為 JSON :
public class PersonSerializer {
private static final Gson defaultGson = new Gson();
public static String toJsonString(Object obj) {
return defaultGson.toJson(obj);
}
}
現在是時候檢查該方法是否有效:
@Test
public void whenUseSerializedAnnotation_thenUseSerializedNameinJsonString() {
String countryJson = PersonSerializer.toJsonString(country);
logger.info(countryJson);
assertFalse("Test failed: No change in the keys", countryJson.contains("countryName"));
assertFalse("Test failed: No change in the keys", countryJson.contains("contentName"));
assertFalse("Test failed: No change in the keys", countryJson.contains("countryCapital"));
assertTrue("Test failed: No change in the keys", countryJson.contains("name"));
assertTrue("Test failed: No change in the keys", countryJson.contains("continent"));
assertTrue("Test failed: No change in the keys", countryJson.contains("capital"));
}
正如預期的那樣,我們發現屬性鍵與我們提供給@SerializedName
註釋的內容相匹配:
{"name":"India","capital":"New Delhi","continent":"Asia"}
讓我們看看相同的註釋是否有助於將上述 JSON 轉換為Country
對象。為此,我們將使用fromJsonString()
方法:
public class PersonSerializer {
private static final Gson defaultGson = new Gson();
public static Country fromJsonString(String json) {
return defaultGson.fromJson(json, Country.class);
}
}
讓我們檢查一下該方法是否有效:
@Test
public void whenJsonStrCreatedWithCustomKeys_thenCreateObjUsingGson() {
String countryJson = PersonSerializer.toJsonString(country);
Country country = PersonSerializer.fromJsonString(countryJson);
assertEquals("Fail: Object creation failed", country.getCountryName(), "India");
assertEquals("Fail: Object creation failed", country.getCountryCapital(), "New Delhi");
assertEquals("Fail: Object creation failed", country.getContinentName(), "Asia");
}
該方法可以創建Country
對象:
Country{countryName='India', countryCapital='New Delhi', continentName='Asia'}
4。結論
在本文中,我們了解了兩個重要的 Gson 註解: @Expose
和@SerializedName.
我們可以自信地說,兩者是完全不同的功能,如此處所示。本文中使用的代碼片段可在 GitHub 上獲取。