Gson
Library
Gson
Overview
Gson is a high-performance JSON library for Java developed by Google. It enables seamless conversion between Java objects and JSON with a concise API and is widely used as the standard in many Java frameworks including Spring Boot. With flexible annotations, custom adapters, and diverse configuration options, it handles complex enterprise-level scenarios. Currently in maintenance mode, it continues to receive bug fixes and minor updates while remaining broadly trusted throughout the Java ecosystem.
Details
Gson 2.13.1 is a mature library with over 10 years of development history. As of 2025, it has entered maintenance mode, but existing bug fixes continue to be applied, providing stable JSON serialization functionality. It features a developer-friendly design with simple toJson/fromJSON methods, rich annotations (@SerializedName, @JsonIgnore, etc.), TypeToken support for generics, and custom serializers/deserializers. However, caution is advised when using it on Android platforms.
Key Features
- Simple API: Intuitive toJson() and fromJson() methods
- Rich Annotations: Fine-grained control with @SerializedName, @Expose, @Since, etc.
- Generics Support: Type-safe collection processing via TypeToken
- Customization: Flexible conversion through custom serializers/deserializers
- Field Exclusion: Multiple exclusion strategies (modifiers, annotations, versioning)
- Wide Adoption: Standard usage in many frameworks including Spring Boot
Pros and Cons
Pros
- Low learning curve with intuitive API for easy Java object-JSON conversion
- Fine-grained configuration control through rich annotations and GsonBuilder
- Safe generic type processing via TypeToken
- Support for complex conversion logic through custom serializers/deserializers
- Enterprise-level reliability backed by over 10 years of track record
- Open source and free with active community support
Cons
- No new feature additions expected due to maintenance mode status
- Not recommended for Android use; Kotlin Serialization or Moshi are preferred alternatives
- Poor compatibility with obfuscation/optimization due to reflection-based approach
- Limited support for JVM language-specific features (Kotlin, Scala)
- May lag behind Jackson and other modern libraries in performance
- Configuration can become complex for intricate JSON schemas
Reference Pages
Code Examples
Basic Setup
<!-- Maven Dependencies -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.13.1</version>
</dependency>
// Gradle Dependencies
dependencies {
implementation 'com.google.code.gson:gson:2.13.1'
}
Basic Serialization and Deserialization
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.util.List;
import java.util.Arrays;
// Basic POJO
class User {
private int id;
private String name;
private String email;
private boolean active;
// Constructor
public User(int id, String name, String email, boolean active) {
this.id = id;
this.name = name;
this.email = email;
this.active = active;
}
// Default constructor (for deserialization)
public User() {}
// getter/setter
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
public boolean isActive() { return active; }
public void setActive(boolean active) { this.active = active; }
}
public class GsonBasicExample {
public static void main(String[] args) {
Gson gson = new Gson();
// Object creation
User user = new User(1, "John Doe", "[email protected]", true);
// 1. Object → JSON string
String jsonString = gson.toJson(user);
System.out.println("JSON string: " + jsonString);
// Output: {"id":1,"name":"John Doe","email":"[email protected]","active":true}
// 2. JSON string → Object
String inputJson = "{\"id\":2,\"name\":\"Jane Smith\",\"email\":\"[email protected]\",\"active\":false}";
User deserializedUser = gson.fromJson(inputJson, User.class);
System.out.println("Deserialized result: " + deserializedUser.getName());
// 3. Array processing
int[] numbers = {1, 2, 3, 4, 5};
String numbersJson = gson.toJson(numbers);
System.out.println("Array JSON: " + numbersJson);
int[] deserializedNumbers = gson.fromJson("[10,20,30]", int[].class);
System.out.println("Array deserialized: " + Arrays.toString(deserializedNumbers));
// 4. Collection processing (using TypeToken)
List<User> users = Arrays.asList(
new User(1, "User 1", "[email protected]", true),
new User(2, "User 2", "[email protected]", false)
);
String usersJson = gson.toJson(users);
System.out.println("User list JSON: " + usersJson);
// Deserialize List<User> using TypeToken
TypeToken<List<User>> userListType = new TypeToken<List<User>>(){};
List<User> deserializedUsers = gson.fromJson(usersJson, userListType.getType());
System.out.println("Deserialized user count: " + deserializedUsers.size());
// 5. Primitive type processing
String stringJson = gson.toJson("Hello Gson");
int intJson = gson.fromJson("42", int.class);
boolean boolJson = gson.fromJson("true", boolean.class);
System.out.println("String JSON: " + stringJson);
System.out.println("Integer deserialized: " + intJson);
System.out.println("Boolean deserialized: " + boolJson);
}
}
Annotations and Customization
import com.google.gson.annotations.*;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
// Advanced annotation usage example
public class AdvancedUser {
@SerializedName("user_id") // Specify JSON property name
private int id;
@SerializedName("full_name")
private String name;
@Expose(serialize = true, deserialize = true) // Explicit exposure control
private String email;
@Expose(serialize = false, deserialize = true) // Write-only
private String password;
@Expose(serialize = true, deserialize = false) // Read-only
private String internalToken;
@Since(1.1) // Valid from version 1.1 onwards
private String newField;
@Until(2.0) // Valid until version 2.0
private String deprecatedField;
private transient String temporaryData; // Excluded from serialization
@JsonAdapter(LocalDateTimeAdapter.class) // Custom adapter specification
private LocalDateTime createdAt;
// Constructor
public AdvancedUser(int id, String name, String email) {
this.id = id;
this.name = name;
this.email = email;
this.createdAt = LocalDateTime.now();
this.internalToken = "internal_" + id;
}
// getter/setter
public int getId() { return id; }
public String getName() { return name; }
public String getEmail() { return email; }
public void setPassword(String password) { this.password = password; }
public LocalDateTime getCreatedAt() { return createdAt; }
}
// Custom adapter example
class LocalDateTimeAdapter implements JsonSerializer<LocalDateTime>, JsonDeserializer<LocalDateTime> {
private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@Override
public JsonElement serialize(LocalDateTime src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(src.format(formatter));
}
@Override
public LocalDateTime deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
return LocalDateTime.parse(json.getAsString(), formatter);
}
}
public class AnnotationExample {
public static void main(String[] args) {
// Basic Gson (processes all fields)
Gson basicGson = new Gson();
// Custom configured Gson
Gson customGson = new GsonBuilder()
.excludeFieldsWithoutExposeAnnotation() // Process only @Expose annotations
.setVersion(1.5) // Set as version 1.5
.setPrettyPrinting() // Formatted output
.serializeNulls() // Output null values
.create();
AdvancedUser user = new AdvancedUser(1, "Advanced User", "[email protected]");
user.setPassword("secret123");
// Basic serialization
String basicJson = basicGson.toJson(user);
System.out.println("Basic JSON:\n" + basicJson);
// Custom configured serialization
String customJson = customGson.toJson(user);
System.out.println("Custom JSON:\n" + customJson);
// Verify annotation control
System.out.println("Only email and password are output due to @Expose annotations");
System.out.println("Version control applied through @Since/@Until annotations");
}
}
Detailed Configuration with GsonBuilder
import com.google.gson.*;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Modifier;
import java.util.Date;
import java.text.DateFormat;
// Custom exclusion strategy implementation
class CustomExclusionStrategy implements ExclusionStrategy {
@Override
public boolean shouldSkipField(FieldAttributes field) {
// Exclude fields starting with "internal"
return field.getName().startsWith("internal");
}
@Override
public boolean shouldSkipClass(Class<?> clazz) {
// Exclude specific classes (e.g., InternalConfig)
return clazz.getSimpleName().equals("InternalConfig");
}
}
public class GsonConfigurationExample {
public static Gson createConfiguredGson() {
return new GsonBuilder()
// Basic settings
.setPrettyPrinting() // Formatted output
.serializeNulls() // Output null values
.disableHtmlEscaping() // Disable HTML escaping
// Date processing
.setDateFormat("yyyy-MM-dd HH:mm:ss") // Date format
.setDateFormat(DateFormat.FULL, DateFormat.FULL) // Locale-aware dates
// Field exclusion settings
.excludeFieldsWithModifiers(Modifier.STATIC, Modifier.TRANSIENT) // Exclude by modifiers
.setExclusionStrategies(new CustomExclusionStrategy()) // Custom exclusion strategy
// Naming conventions
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) // snake_case
// Version management
.setVersion(2.0) // Set as version 2.0
// Complex Map key support
.enableComplexMapKeySerialization()
// Error handling
.setLenient() // Allow non-strict JSON parsing
.create();
}
public static void demonstrateConfiguration() {
Gson gson = createConfiguredGson();
// Test data
TestData data = new TestData();
data.name = "Configuration Test";
data.createdAt = new Date();
data.internalId = "internal_123"; // Field to be excluded
data.publicId = "public_456";
// Serialization
String json = gson.toJson(data);
System.out.println("Configured JSON:\n" + json);
// Complex Map key example
Map<ComplexKey, String> complexMap = new HashMap<>();
complexMap.put(new ComplexKey("key1", 100), "value1");
complexMap.put(new ComplexKey("key2", 200), "value2");
String complexJson = gson.toJson(complexMap);
System.out.println("Complex Map key JSON:\n" + complexJson);
// Deserialization
TestData deserializedData = gson.fromJson(json, TestData.class);
System.out.println("Deserialized result: " + deserializedData.name);
}
static class TestData {
String name;
Date createdAt;
String internalId; // Excluded by CustomExclusionStrategy
String publicId;
private static String staticField = "static"; // Excluded by modifier
private transient String transientField = "transient"; // Excluded by modifier
}
static class ComplexKey {
String name;
int value;
ComplexKey(String name, int value) {
this.name = name;
this.value = value;
}
// equals/hashCode implementation required
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
ComplexKey that = (ComplexKey) obj;
return value == that.value && Objects.equals(name, that.name);
}
@Override
public int hashCode() {
return Objects.hash(name, value);
}
}
}
JSON Parsing and Manipulation (using JsonElement)
import com.google.gson.*;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import java.io.StringReader;
import java.io.StringWriter;
public class JsonElementExample {
public static void jsonElementOperations() {
Gson gson = new Gson();
// JSON string
String jsonString = """
{
"user": {
"id": 123,
"name": "JSON Operations User",
"contact": {
"email": "[email protected]",
"phone": "555-1234"
},
"hobbies": ["reading", "movies", "programming"]
},
"metadata": {
"version": "1.0",
"timestamp": "2025-01-01T12:00:00Z"
}
}
""";
// Parse as JsonElement
JsonElement rootElement = JsonParser.parseString(jsonString);
// Read values
JsonObject root = rootElement.getAsJsonObject();
JsonObject user = root.getAsJsonObject("user");
int userId = user.get("id").getAsInt();
String userName = user.get("name").getAsString();
String email = user.getAsJsonObject("contact").get("email").getAsString();
System.out.println("User information:");
System.out.println("ID: " + userId);
System.out.println("Name: " + userName);
System.out.println("Email: " + email);
// Array processing
JsonArray hobbies = user.getAsJsonArray("hobbies");
System.out.println("Hobbies:");
for (JsonElement hobby : hobbies) {
System.out.println(" - " + hobby.getAsString());
}
// Conditional access
if (root.has("metadata")) {
JsonObject metadata = root.getAsJsonObject("metadata");
String version = metadata.get("version").getAsString();
System.out.println("Version: " + version);
}
// Null value check
JsonElement description = user.get("description");
if (description == null || description.isJsonNull()) {
System.out.println("Description field does not exist or is null");
}
}
public static void jsonElementModification() {
// Create new JSON object
JsonObject root = new JsonObject();
// Add primitive values
root.addProperty("name", "New User");
root.addProperty("age", 25);
root.addProperty("active", true);
root.addProperty("score", 95.5);
// Create nested object
JsonObject contact = new JsonObject();
contact.addProperty("email", "[email protected]");
contact.addProperty("phone", "555-9876");
root.add("contact", contact);
// Create array
JsonArray skills = new JsonArray();
skills.add("Java");
skills.add("JSON");
skills.add("Gson");
root.add("skills", skills);
// Add existing object
User existingUser = new User(999, "Existing User", "[email protected]", true);
root.add("existing_user", JsonParser.parseString(new Gson().toJson(existingUser)));
// Output result
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String result = gson.toJson(root);
System.out.println("Created JSON:\n" + result);
// Partial modifications
root.addProperty("age", 26); // Update age
root.getAsJsonObject("contact").addProperty("address", "New York"); // Add address
skills.add("Spring Boot"); // Add skill
System.out.println("Updated JSON:\n" + gson.toJson(root));
}
public static void streamingJsonProcessing() {
try {
// Streaming write
StringWriter stringWriter = new StringWriter();
JsonWriter writer = new JsonWriter(stringWriter);
writer.setIndent(" "); // Set indentation
writer.beginObject();
writer.name("users").beginArray();
// Streaming processing of large data
for (int i = 1; i <= 1000; i++) {
writer.beginObject();
writer.name("id").value(i);
writer.name("name").value("User " + i);
writer.name("active").value(i % 2 == 0);
writer.name("score").value(i * 0.95);
writer.endObject();
if (i % 100 == 0) {
System.out.println("Processed: " + i + " users");
}
}
writer.endArray();
writer.endObject();
writer.close();
String jsonResult = stringWriter.toString();
System.out.println("Streaming processing complete: " + jsonResult.length() + " characters");
// Streaming read
JsonReader reader = new JsonReader(new StringReader(jsonResult));
reader.beginObject();
while (reader.hasNext()) {
String name = reader.nextName();
if ("users".equals(name)) {
reader.beginArray();
int count = 0;
while (reader.hasNext()) {
reader.beginObject();
int id = 0;
String userName = "";
boolean active = false;
while (reader.hasNext()) {
String fieldName = reader.nextName();
switch (fieldName) {
case "id":
id = reader.nextInt();
break;
case "name":
userName = reader.nextString();
break;
case "active":
active = reader.nextBoolean();
break;
case "score":
reader.nextDouble(); // Skip
break;
}
}
reader.endObject();
count++;
if (active && id <= 10) {
System.out.println("Active user: " + userName);
}
}
reader.endArray();
System.out.println("Streaming read complete: " + count + " users");
}
}
reader.endObject();
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
System.out.println("=== JsonElement Operations Example ===");
jsonElementOperations();
System.out.println("\n=== JsonElement Modification Example ===");
jsonElementModification();
System.out.println("\n=== Streaming Processing Example ===");
streamingJsonProcessing();
}
}
Error Handling and Best Practices
import com.google.gson.*;
import java.lang.reflect.Type;
public class GsonErrorHandlingExample {
public static void comprehensiveErrorHandling() {
Gson gson = new Gson();
// 1. Basic error handling
try {
String invalidJson = "{\"name\": John Doe, \"age\": }"; // Invalid JSON
User user = gson.fromJson(invalidJson, User.class);
} catch (JsonSyntaxException e) {
System.out.println("JSON syntax error: " + e.getMessage());
}
// 2. Type mismatch error
try {
String wrongTypeJson = "{\"id\": \"string\", \"name\": \"Test User\"}";
User user = gson.fromJson(wrongTypeJson, User.class);
} catch (JsonSyntaxException e) {
System.out.println("Type conversion error: " + e.getMessage());
}
// 3. Safe deserialization
User safeUser = safeDeserialize("{\"id\": 123, \"name\": \"Safe User\"}", User.class);
if (safeUser != null) {
System.out.println("Safely deserialized: " + safeUser.getName());
}
// 4. Partial JSON parsing
String partialJson = "{\"validField\": \"value\", \"invalidField\": }";
JsonObject partial = parsePartialJson(partialJson);
if (partial != null) {
System.out.println("Partial parse result: " + partial.toString());
}
// 5. Robust Gson configuration
Gson robustGson = createRobustGson();
String flexibleJson = """
{
"id": "123",
"name": "Robust User",
"email": "[email protected]",
"unknownField": "This will be ignored"
}
""";
User robustUser = safeDeserialize(flexibleJson, User.class, robustGson);
if (robustUser != null) {
System.out.println("Robust deserialization: " + robustUser.getName());
}
}
// Safe deserialization method
public static <T> T safeDeserialize(String json, Class<T> clazz) {
return safeDeserialize(json, clazz, new Gson());
}
public static <T> T safeDeserialize(String json, Class<T> clazz, Gson gson) {
try {
return gson.fromJson(json, clazz);
} catch (JsonSyntaxException e) {
System.err.println("JSON syntax error: " + e.getMessage());
return null;
} catch (JsonIOException e) {
System.err.println("JSON IO error: " + e.getMessage());
return null;
} catch (JsonParseException e) {
System.err.println("JSON parse error: " + e.getMessage());
return null;
} catch (Exception e) {
System.err.println("Unexpected error: " + e.getMessage());
return null;
}
}
// Partial JSON parsing
public static JsonObject parsePartialJson(String json) {
try {
return JsonParser.parseString(json).getAsJsonObject();
} catch (JsonSyntaxException e) {
System.err.println("Error during partial parsing: " + e.getMessage());
// Attempt to extract valid parts as much as possible
try {
int lastValidIndex = findLastValidJsonIndex(json);
if (lastValidIndex > 0) {
String truncatedJson = json.substring(0, lastValidIndex);
return JsonParser.parseString(truncatedJson).getAsJsonObject();
}
} catch (Exception innerE) {
System.err.println("Recovery attempt also failed: " + innerE.getMessage());
}
return null;
}
}
// Robust Gson configuration
public static Gson createRobustGson() {
return new GsonBuilder()
.setLenient() // Allow non-strict JSON
.serializeNulls() // Serialize null values
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) // Naming convention
.registerTypeAdapter(String.class, new StringDeserializer()) // Custom deserializer
.registerTypeAdapter(Integer.class, new SafeIntegerDeserializer()) // Safe integer deserializer
.create();
}
// Simple valid JSON index search (requires more robust implementation in practice)
private static int findLastValidJsonIndex(String json) {
int braceCount = 0;
for (int i = 0; i < json.length(); i++) {
char c = json.charAt(i);
if (c == '{') braceCount++;
else if (c == '}') braceCount--;
if (braceCount == 0 && i > 0) {
return i + 1;
}
}
return -1;
}
// Custom string deserializer
static class StringDeserializer implements JsonDeserializer<String> {
@Override
public String deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
if (json.isJsonNull()) {
return null;
}
if (json.isJsonPrimitive()) {
return json.getAsString();
}
// Convert non-strings to string
return json.toString();
}
}
// Safe integer deserializer
static class SafeIntegerDeserializer implements JsonDeserializer<Integer> {
@Override
public Integer deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
if (json.isJsonNull()) {
return null;
}
try {
if (json.isJsonPrimitive()) {
JsonPrimitive primitive = json.getAsJsonPrimitive();
if (primitive.isNumber()) {
return primitive.getAsInt();
}
if (primitive.isString()) {
return Integer.parseInt(primitive.getAsString());
}
}
return 0; // Default value
} catch (NumberFormatException e) {
System.err.println("Integer conversion error, using default value 0: " + json);
return 0;
}
}
}
// Deserialization with performance metrics
public static <T> T deserializeWithMetrics(String json, Class<T> clazz) {
long startTime = System.nanoTime();
long memoryBefore = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
try {
Gson gson = new Gson();
T result = gson.fromJson(json, clazz);
long endTime = System.nanoTime();
long memoryAfter = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
double durationMs = (endTime - startTime) / 1_000_000.0;
long memoryUsed = memoryAfter - memoryBefore;
System.out.println("Deserialization time: " + String.format("%.2f", durationMs) + "ms");
System.out.println("Memory usage: " + memoryUsed + " bytes");
return result;
} catch (Exception e) {
long endTime = System.nanoTime();
double durationMs = (endTime - startTime) / 1_000_000.0;
System.err.println("Error occurred (elapsed time: " + String.format("%.2f", durationMs) + "ms): " + e.getMessage());
return null;
}
}
public static void main(String[] args) {
System.out.println("=== Gson Error Handling Example ===");
comprehensiveErrorHandling();
// Performance metrics deserialization test
System.out.println("\n=== Performance Measurement Example ===");
String testJson = new Gson().toJson(new User(1, "Metrics Test", "[email protected]", true));
User metricsUser = deserializeWithMetrics(testJson, User.class);
if (metricsUser != null) {
System.out.println("Measurement result: " + metricsUser.getName());
}
}
}
Instance Creation and Custom Adapters
import com.google.gson.*;
import java.lang.reflect.Type;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
// Custom InstanceCreator
class UserInstanceCreator implements InstanceCreator<User> {
@Override
public User createInstance(Type type) {
// Create User instance with default values
return new User(0, "Default User", "[email protected]", false);
}
}
// Complex object adapter
class ConfigurationAdapter implements JsonSerializer<Configuration>, JsonDeserializer<Configuration> {
@Override
public JsonElement serialize(Configuration src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("version", src.getVersion());
jsonObject.addProperty("environment", src.getEnvironment());
jsonObject.add("features", context.serialize(src.getFeatures()));
jsonObject.addProperty("timestamp", src.getCreatedAt().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
// Exclude sensitive information
if (!src.getEnvironment().equals("production")) {
jsonObject.addProperty("debug", src.isDebugMode());
}
return jsonObject;
}
@Override
public Configuration deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
JsonObject jsonObject = json.getAsJsonObject();
Configuration config = new Configuration();
config.setVersion(jsonObject.get("version").getAsString());
config.setEnvironment(jsonObject.get("environment").getAsString());
// Deserialize features
Type listType = new TypeToken<List<String>>(){}.getType();
List<String> features = context.deserialize(jsonObject.get("features"), listType);
config.setFeatures(features);
// Convert timestamp to LocalDateTime
String timestamp = jsonObject.get("timestamp").getAsString();
config.setCreatedAt(LocalDateTime.parse(timestamp, DateTimeFormatter.ISO_LOCAL_DATE_TIME));
// Set debug field only if it exists
if (jsonObject.has("debug")) {
config.setDebugMode(jsonObject.get("debug").getAsBoolean());
}
return config;
}
}
// Configuration class
class Configuration {
private String version;
private String environment;
private List<String> features;
private boolean debugMode;
private LocalDateTime createdAt;
public Configuration() {
this.createdAt = LocalDateTime.now();
this.features = new ArrayList<>();
}
// getter/setter
public String getVersion() { return version; }
public void setVersion(String version) { this.version = version; }
public String getEnvironment() { return environment; }
public void setEnvironment(String environment) { this.environment = environment; }
public List<String> getFeatures() { return features; }
public void setFeatures(List<String> features) { this.features = features; }
public boolean isDebugMode() { return debugMode; }
public void setDebugMode(boolean debugMode) { this.debugMode = debugMode; }
public LocalDateTime getCreatedAt() { return createdAt; }
public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; }
}
public class AdvancedAdapterExample {
public static void demonstrateCustomAdapters() {
// Create Gson with registered custom adapters
Gson gson = new GsonBuilder()
.registerTypeAdapter(User.class, new UserInstanceCreator())
.registerTypeAdapter(Configuration.class, new ConfigurationAdapter())
.setPrettyPrinting()
.create();
// Create Configuration object
Configuration config = new Configuration();
config.setVersion("2.1.0");
config.setEnvironment("development");
config.setFeatures(Arrays.asList("auth", "logging", "metrics", "cache"));
config.setDebugMode(true);
// Serialization
String configJson = gson.toJson(config);
System.out.println("Configuration JSON:\n" + configJson);
// Deserialization
Configuration deserializedConfig = gson.fromJson(configJson, Configuration.class);
System.out.println("Deserialized result:");
System.out.println("Version: " + deserializedConfig.getVersion());
System.out.println("Environment: " + deserializedConfig.getEnvironment());
System.out.println("Feature count: " + deserializedConfig.getFeatures().size());
System.out.println("Debug mode: " + deserializedConfig.isDebugMode());
// Production environment behavior (debug field excluded)
config.setEnvironment("production");
String prodJson = gson.toJson(config);
System.out.println("\nProduction environment JSON:\n" + prodJson);
// InstanceCreator behavior verification
String emptyUserJson = "{}"; // UserInstanceCreator works even with empty JSON
User defaultUser = gson.fromJson(emptyUserJson, User.class);
System.out.println("\nInstanceCreator result: " + defaultUser.getName());
}
public static void main(String[] args) {
System.out.println("=== Custom Adapter Example ===");
demonstrateCustomAdapters();
}
}