← Назад к вопросам

Что такое Gson поля?

2.2 Middle🔥 91 комментариев
#Основы Java

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое 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 и сторонними сервисами.

Что такое Gson поля? | PrepBro