Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Что такое Gson поля (@SerializedName, @Expose, @Transient)
Gson — это популярная Java-библиотека от Google для сериализации и десериализации объектов в/из JSON. Когда работаешь с Gson, часто встречаешься с аннотациями, которые управляют процессом преобразования объектов в JSON и обратно.
Основные аннотации Gson
1. @SerializedName
Определяет название поля в JSON, отличное от названия в Java классе:
import com.google.gson.annotations.SerializedName;
public class User {
@SerializedName("full_name") // В JSON это будет "full_name", а не "fullName"
private String fullName;
@SerializedName("user_id")
private Long userId;
@SerializedName("created_at")
private LocalDateTime createdAt;
}
Это полезно, когда API возвращает JSON с snake_case, а код использует camelCase:
Gson gson = new Gson();
String json = "{\"full_name\":\"John Doe\",\"user_id\":123}";
User user = gson.fromJson(json, User.class);
// user.fullName = "John Doe"
// user.userId = 123
String jsonOut = gson.toJson(user);
// {"full_name":"John Doe","user_id":123}
Альтернативные названия с @SerializedName:
public class Product {
@SerializedName(value = "product_name", alternate = {"name", "title"})
private String productName;
}
Gson gson = new Gson();
// Может десериализоваться из JSON с "product_name", "name" или "title"
Product p1 = gson.fromJson("{\"product_name\":\"Phone\"}", Product.class);
Product p2 = gson.fromJson("{\"name\":\"Phone\"}", Product.class);
Product p3 = gson.fromJson("{\"title\":\"Phone\"}", Product.class);
// Все три сработают
2. @Expose
Контролирует, включается ли поле при сериализации и десериализации:
import com.google.gson.annotations.Expose;
public class UserProfile {
@Expose
private String username; // Будет включено в JSON
@Expose(serialize = true, deserialize = false)
private String email; // Сериализуется, но не десериализуется
@Expose(serialize = false, deserialize = true)
private String password; // Десериализуется, но не сериализуется
private String internalId; // Без @Expose - не включается в JSON
}
Для работы @Expose нужно создать GsonBuilder с excludeFieldsWithoutExposeAnnotation():
Gson gson = new GsonBuilder()
.excludeFieldsWithoutExposeAnnotation() // Только поля с @Expose
.create();
UserProfile profile = new UserProfile("john", "john@example.com", "secret123");
String json = gson.toJson(profile);
// {"username":"john","email":"john@example.com"}
// password и internalId не включены
UserProfile restored = gson.fromJson(json, UserProfile.class);
// restored.username = "john"
// restored.password = null (не был десериализован)
3. @Transient
Полностью исключает поле из сериализации и десериализации:
public class Order {
@Expose
private Long orderId;
@Expose
private BigDecimal totalAmount;
@Transient
private transient String internalProcessingStatus; // Не в JSON
@Transient
private transient Connection databaseConnection; // Не в JSON
}
Это полезно для полей, которые:
- Используются только во время обработки
- Содержат несериализуемые объекты (Connection, Socket)
- Являются временным кэшем
Пример: полный REST API DTO
import com.google.gson.annotations.SerializedName;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.Transient;
public class UserDTO {
@Expose
@SerializedName("user_id")
private Long userId;
@Expose
@SerializedName("full_name")
private String fullName;
@Expose
private String email;
@Expose(serialize = false)
@SerializedName("password_hash")
private String passwordHash; // Только десериализуется (при создании)
@Expose(deserialize = false)
@SerializedName("created_at")
private LocalDateTime createdAt; // Только сериализуется (при отправке)
@Transient
private transient String tempToken; // Не в JSON
public UserDTO(String fullName, String email, String passwordHash) {
this.fullName = fullName;
this.email = email;
this.passwordHash = passwordHash;
}
}
При создании пользователя (POST):
{
"full_name": "John Doe",
"email": "john@example.com",
"password_hash": "hashed_password_here"
}
При возврате пользователя (GET):
{
"user_id": 1,
"full_name": "John Doe",
"email": "john@example.com",
"created_at": "2025-03-23T10:30:00"
}
Практический пример: API с Gson
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class GsonApiExample {
private static final Gson GSON = new GsonBuilder()
.excludeFieldsWithoutExposeAnnotation() // Только @Expose поля
.registerTypeAdapter(
LocalDateTime.class,
(JsonDeserializer<LocalDateTime>) (json, typeOfT, context) ->
LocalDateTime.parse(json.getAsString(),
DateTimeFormatter.ISO_DATE_TIME)
)
.setPrettyPrinting() // Красивый вывод
.create();
public static void main(String[] args) {
// Десериализация (JSON → Object)
String jsonInput = "{\"full_name\":\"Alice\",\"email\":\"alice@example.com\"}";
UserDTO user = GSON.fromJson(jsonInput, UserDTO.class);
System.out.println("Deserialize: " + user.getFullName());
// Сериализация (Object → JSON)
user.setUserId(42L);
user.setCreatedAt(LocalDateTime.now());
String jsonOutput = GSON.toJson(user);
System.out.println("Serialize: " + jsonOutput);
}
}
Сравнение аннотаций
| Аннотация | Сериализация | Десериализация | Использование |
|---|---|---|---|
| @SerializedName | ✅ | ✅ | Переименовать поле в JSON |
| @Expose | ✅/❌ | ✅/❌ | Включить/исключить из JSON |
| @Transient | ❌ | ❌ | Полностью исключить поле |
Альтернативы Gson
Jackson (более популярен в Spring):
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonIgnore;
public class UserJackson {
@JsonProperty("full_name")
private String fullName;
@JsonIgnore
private String internalId;
}
JSON-B (Jakarta EE):
import jakarta.json.bind.annotation.JsonbProperty;
import jakarta.json.bind.annotation.JsonbTransient;
public class UserJsonB {
@JsonbProperty("full_name")
private String fullName;
@JsonbTransient
private String internalId;
}
Лучшие практики
1. Используй @SerializedName для совместимости API:
public class ApiResponse {
@SerializedName("result")
private String result; // API возвращает "result"
}
2. Защищай чувствительные данные с @Expose(deserialize = false):
public class User {
@Expose(deserialize = false) // Никогда не заполняй из JSON
private String password;
}
3. Используй @Transient для временных данных:
public class Order {
@Transient
private transient PaymentProcessor processor; // Не сериализуется
}
4. Создавай отдельные DTO для API:
// Entity
public class UserEntity {
private Long id;
private String name;
private String internalSecret;
}
// DTO для API
public class UserDTO {
@SerializedName("user_id")
@Expose
private Long id;
@Expose
private String name;
// internalSecret не попадает в API
}
Гсон-аннотации — это мощный инструмент для контроля сериализации, особенно при работе с REST API и сторонними сервисами.