知識庫 / JSON RSS 訂閱

Gson 中的 @Expose 和 @SerializedName 註解

JSON
HongKong
5
09:41 PM · Dec 05 ,2025

1. 簡介

Gson 是 Google 開發的一個開源 Java 庫,用於簡化對象與 JSON 之間的轉換。它提供高效的序列化和反序列化技術,並支持複雜對象。

諸如 Gson 這樣的庫可以提供對 JSON 的直接映射到 POJO(Java 規範對象)的支持。然而,在序列化和反序列化過程中,有時需要排除特定的屬性。

在本教程中,我們將討論 Gson 庫中常用的兩個關鍵註解:<em @Expose</em><em @SerializedName</em>。雖然這兩個註解都與屬性的可序列化和可反序列化有關,但它們具有不同的使用場景。

2. Gson 安裝配置

要開始使用 Gson,我們在 Maven 中添加其依賴項:

<pom.xml> 文件中:

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.10.1</version>
</dependency>

3. 在 Gson 中使用 <em @Expose>

Gson 的默認行為是在不指定其他情況的前提下,序列化和反序列化 POJO 類中的所有字段。可以使用 <em @Expose> 註解來覆蓋此行為,並控制特定字段在序列化和反序列化中的包含或排除

Gson 僅在其 <em serialize 和 <em deserialize 屬性設置為 <em true 的情況下,將帶有 @<em @Expose> 註解的字段包含在輸出的 JSON 中。 默認情況下,<em serialize 或 <em deserialize 屬性的值為 <em true。

讓我們來看一個例子。 我們將使用一個 <em User 類,該類具有 <em id、<em name、<em age 和 <em email 屬性。 電子郵件是敏感信息,因此我們將排除它在輸出 JSON 中的序列化。

public class User {

    @Expose
    String name;

    @Expose
    int age;

    @Expose(serialize = true, deserialize = false)
    long id;
    
    @Expose(serialize = false, deserialize = false)
    private String email;

    // Constructors, Getters, and Setters
}

在上述代碼片段中,我們對 nameage 字段進行了 @Expose 註解。 缺少顯式的 serializedeserialize 屬性表明它們默認為 true

我們還應該注意到,email 屬性的兩個註解都設置為 false。因此,序列化的 JSON 會忽略 email 字段。但是,在創建 GsonBuilder 實例時,應該使用 excludeFieldsWithoutExposeAnnotation() 方法才能實現這一點。

另一方面,對於 id,序列化過程會包含它,而反序列化則會忽略 JSON 中存在的任何 id

@Test
public void givenUserObject_whenSerialized_thenCorrectJsonProduced() {
    User user = new User("John Doe", 30, "[email protected]");
    user.setId(12345L);

    Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
    String json = gson.toJson(user);

    // Verify that name, age, and id are serialized, but email is not
    assertEquals("{\"name\":\"John Doe\",\"age\":30,\"id\":12345}", json);
}
@Test
public void givenJsonInput_whenDeserialized_thenCorrectUserObjectProduced() {
    String jsonInput = "{\"name\":\"Jane Doe\",\"age\":25,\"id\":67890,\"email\":\"[email protected]\"}";

    Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation()
      .create();
    User user = gson.fromJson(jsonInput, User.class);

    // Verify that name and age are deserialized, but email and id are not
    assertEquals("Jane Doe", user.name);
    assertEquals(25, user.getAge());
    assertEquals(0, user.getId()); // id is not deserialized
    assertNull(user.getEmail()); // email is not deserialized
}

在第一個測試中,我們發現序列化的JSON中不包含email屬性。在第二個單元測試中,我們斷言反序列化的User對象忽略了JSON中的email字段。

4. Gson 中的 @SerializedName 註解

讓我們理解 Gson 中 @SerializedName 註解的使用。當我們創建 Java 類並定義其屬性時,JSON 表示可能需要與類中定義的名稱不同的名稱。 此註解將 POJO 屬性映射到其序列化的 JSON 表示中的特定名稱。

以下是我們的先前示例,現在我們希望 User 的 JSON 表示中 firstName 是字段名稱,而不是 name

public class User {

    @Expose
    @SerializedName("firstName")
    String name;
}

我們的單元測試現在應該斷言 firstName 字段:

@Test
public void givenUserObject_whenSerialized_thenCorrectJsonProduced() {
    User user = new User("John Doe", 30, "[email protected]");
    user.setId(12345L);

    Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
    String json = gson.toJson(user);

    assertEquals("{\"firstName\":\"John Doe\",\"age\":30,\"id\":12345}", json);
}

@SerailizedName 支持一個額外的屬性,即 alternate,它接受一個包含屬性的備用名稱列表,並告知解析器在反序列化時查找其中任何一個值。 此功能在屬性名稱可能因外部或遺留系統而異時非常強大。

讓我們考慮一個使用 fullName 而不是 firstName 的系統。通過正確填充 alternate 屬性,我們可以正確解碼它們。

public class User {

    @Expose
    @SerializedName(value = "firstName", alternate = { "fullName", "name" })
    String name;
}
@Test
public void givenJsonWithAlternateNames_whenDeserialized_thenCorrectNameFieldMapped() {
    String jsonInput1 = "{\"firstName\":\"Jane Doe\",\"age\":25,\"id\":67890,\"email\":\"[email protected]\"}";
    String jsonInput2 = "{\"fullName\":\"John Doe\",\"age\":30,\"id\":12345,\"email\":\"[email protected]\"}";
    String jsonInput3 = "{\"name\":\"Alice\",\"age\":28,\"id\":54321,\"email\":\"[email protected]\"}";

    Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();

    User user1 = gson.fromJson(jsonInput1, User.class);
    User user2 = gson.fromJson(jsonInput2, User.class);
    User user3 = gson.fromJson(jsonInput3, User.class);

    // Verify that the name field is correctly deserialized from different JSON field names
    assertEquals("Jane Doe", user1.getName());
    assertEquals("John Doe", user2.getName());
    assertEquals("Alice", user3.getName());
}

我們能夠正確地從輸入 JSON 報文中反序列化 name 屬性,其中 fullNamefirstName 是屬性名稱。

5. @SerializedName@Expose 的區別

以下是這兩種註解的主要區別的總結:

@SerializedName @Expose
將 Java POJO 字段映射到 JSON 字段名稱 指示字段是否應進行序列化或反序列化
一個 value 屬性是必需的,並且有一個可選的 alternate 屬性可用於使用 有兩個可選屬性可用:serializedeserialize
無需任何配置即可工作 僅在配置了 GsonBuilder 時才有效,並且需要使用 GsonBuilder.excludeFieldsWithoutExposeAnnotation()

6. 結論

在本文中,我們瞭解了 @SerializedName@Expose 的工作原理,以及如何利用它們在 Java 中處理 JSON 的序列化和反序列化。我們還強調了兩者之間的主要差異。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.