Android Gson框架源码深度解析(1)

码字不易,请大佬们点点关注,谢谢~

一、Gson框架概述与核心定位

1.1 JSON数据格式与Android开发需求

JSON(JavaScript Object Notation)作为一种轻量级的数据交换格式,因其简洁性和跨平台兼容性,在现代Android开发中被广泛应用于网络数据传输和本地数据存储。Android应用需要高效、可靠的方式将JSON数据与Java对象相互转换,Gson正是满足这一需求的主流解决方案之一。

1.2 Gson框架的诞生与发展历程

Gson由Google开发并维护,最初作为Google内部项目的一部分,于2008年开源。其设计目标是提供一种简单、灵活且高性能的JSON处理库,支持复杂Java对象与JSON数据的相互转换。随着Android平台的兴起,Gson因其易用性和强大功能,逐渐成为Android开发中处理JSON数据的首选框架之一。

1.3 Gson在Android生态中的地位与竞品对比

在Android生态中,处理JSON数据的框架众多,包括Jackson、Moshi、FastJSON等。与这些框架相比,Gson具有以下优势:

  • 稳定性高:作为Google官方维护的库,Gson在Android平台上具有良好的兼容性和稳定性。
  • 功能全面:支持复杂泛型、嵌套对象、自定义序列化/反序列化等高级特性。
  • 易用性强:API设计简洁直观,降低了开发者的学习成本。
  • 社区活跃:拥有庞大的开发者社区,文档丰富,问题响应及时。

二、Gson基础使用示例详解

2.1 简单Java对象与JSON的互转

2.1.1 基本数据类型的转换

Gson可以轻松处理基本数据类型与JSON的互转。例如,将一个包含基本数据类型的Java对象转换为JSON字符串:

java 复制代码
// 创建Gson实例,使用默认配置
Gson gson = new Gson();

// 定义一个包含基本数据类型的Java类
class User {
    private String name;  // 字符串类型字段
    private int age;      // 整数类型字段
    private boolean isStudent;  // 布尔类型字段
    
    // 构造方法
    public User(String name, int age, boolean isStudent) {
        this.name = name;
        this.age = age;
        this.isStudent = isStudent;
    }
    
    // Getter和Setter方法
    public String getName() { return name; }
    public int getAge() { return age; }
    public boolean isStudent() { return isStudent; }
}

// 创建Java对象
User user = new User("John Doe", 30, true);

// 将Java对象转换为JSON字符串
String json = gson.toJson(user);
// 输出结果: {"name":"John Doe","age":30,"isStudent":true}

从源码角度分析,gson.toJson(user)方法的执行流程如下:

  1. Gson实例内部维护了一个TypeAdapterFactory列表,用于查找合适的TypeAdapter处理对象序列化。
  2. 对于User类这种普通Java对象,Gson会使用ReflectiveTypeAdapterFactory创建一个ReflectiveTypeAdapter
  3. ReflectiveTypeAdapter通过反射获取User类的所有字段(包括私有字段),并遍历这些字段。
  4. 对于每个字段,根据其类型查找对应的TypeAdapter(如String类型使用StringTypeAdapter)。
  5. 调用各字段的TypeAdapterwrite方法,将字段值写入JsonWriter,最终生成JSON字符串。
2.1.2 JSON字符串转换为Java对象

将JSON字符串转换为Java对象的过程如下:

java 复制代码
// 定义JSON字符串
String json = "{\"name\":\"John Doe\",\"age\":30,\"isStudent\":true}";

// 将JSON字符串转换为Java对象
User user = gson.fromJson(json, User.class);

// 访问Java对象的字段
System.out.println("Name: " + user.getName());    // 输出: Name: John Doe
System.out.println("Age: " + user.getAge());      // 输出: Age: 30
System.out.println("Is Student: " + user.isStudent());  // 输出: Is Student: true

源码层面,gson.fromJson(json, User.class)方法的执行流程为:

  1. Gson同样通过TypeAdapterFactory列表查找处理User类的TypeAdapter,最终找到ReflectiveTypeAdapter
  2. 创建JsonReader解析JSON字符串,并将其定位到对象开始处。
  3. ReflectiveTypeAdapter通过反射创建User类的实例。
  4. 遍历JSON对象的每个属性,根据属性名查找User类中对应的字段。
  5. 使用字段类型对应的TypeAdapterJsonReader读取值,并通过反射设置到User实例的对应字段中。

2.2 集合类型的JSON处理

2.2.1 列表集合的序列化与反序列化

处理包含多个对象的列表集合时,需要使用TypeToken来指定泛型类型:

java 复制代码
// 创建包含多个User对象的列表
List<User> userList = new ArrayList<>();
userList.add(new User("Alice", 25, true));
userList.add(new User("Bob", 35, false));

// 将列表序列化为JSON字符串
String jsonList = gson.toJson(userList);
// 输出结果: [{"name":"Alice","age":25,"isStudent":true},{"name":"Bob","age":35,"isStudent":false}]

// 将JSON字符串反序列化为列表
Type userListType = new TypeToken<List<User>>(){}.getType();
List<User> parsedList = gson.fromJson(jsonList, userListType);

// 遍历列表
for (User user : parsedList) {
    System.out.println("Name: " + user.getName() + ", Age: " + user.getAge());
}

源码分析:

  • 序列化过程 :Gson通过ListTypeAdapterFactory创建处理ListTypeAdapter,遍历列表中的每个元素,调用其对应类型的TypeAdapter进行序列化。
  • 反序列化过程 :由于Java泛型的类型擦除特性,需要使用TypeToken来保留泛型信息。Gson通过TypeToken获取具体的泛型类型(如List<User>),然后创建相应的TypeAdapter解析JSON数组,并将每个元素转换为User对象。
2.2.2 映射集合的处理

处理Map类型时,同样需要使用TypeToken

java 复制代码
// 创建包含User对象的映射
Map<String, User> userMap = new HashMap<>();
userMap.put("user1", new User("Charlie", 40, false));
userMap.put("user2", new User("David", 28, true));

// 将映射序列化为JSON字符串
String jsonMap = gson.toJson(userMap);
// 输出结果: {"user1":{"name":"Charlie","age":40,"isStudent":false},"user2":{"name":"David","age":28,"isStudent":true}}

// 将JSON字符串反序列化为映射
Type userMapType = new TypeToken<Map<String, User>>(){}.getType();
Map<String, User> parsedMap = gson.fromJson(jsonMap, userMapType);

// 遍历映射
for (Map.Entry<String, User> entry : parsedMap.entrySet()) {
    System.out.println("Key: " + entry.getKey() + ", Name: " + entry.getValue().getName());
}

源码角度:

  • 序列化过程 :Gson使用MapTypeAdapterFactory创建处理MapTypeAdapter,遍历Map的每个键值对,分别序列化键和值。
  • 反序列化过程 :通过TypeToken获取Map的泛型类型信息,解析JSON对象的每个属性,将属性名作为键,属性值作为值,构建Map对象。

2.3 复杂嵌套对象的处理

当Java对象包含嵌套结构时,Gson同样能正确处理:

java 复制代码
// 定义包含嵌套对象的类
class Company {
    private String name;  // 公司名称
    private List<User> employees;  // 员工列表
    
    public Company(String name, List<User> employees) {
        this.name = name;
        this.employees = employees;
    }
    
    public String getName() { return name; }
    public List<User> getEmployees() { return employees; }
}

// 创建包含嵌套结构的对象
List<User> employees = new ArrayList<>();
employees.add(new User("Eve", 29, true));
employees.add(new User("Frank", 33, false));
Company company = new Company("Acme Inc.", employees);

// 将嵌套对象序列化为JSON字符串
String jsonCompany = gson.toJson(company);
// 输出结果: {"name":"Acme Inc.","employees":[{"name":"Eve","age":29,"isStudent":true},{"name":"Frank","age":33,"isStudent":false}]}

// 将JSON字符串反序列化为嵌套对象
Company parsedCompany = gson.fromJson(jsonCompany, Company.class);

// 访问嵌套对象的字段
System.out.println("Company: " + parsedCompany.getName());
for (User employee : parsedCompany.getEmployees()) {
    System.out.println("  Employee: " + employee.getName());
}

源码分析:

  • 序列化过程 :Gson递归处理嵌套对象。对于Company类,先序列化其name字段,再处理employees列表,对列表中的每个User对象进行序列化。
  • 反序列化过程 :先创建Company实例,然后解析JSON中的name字段并设置到实例中,接着解析employees数组,将每个元素转换为User对象并添加到employees列表中。

2.4 自定义序列化与反序列化

在某些场景下,默认的序列化/反序列化行为可能不符合需求,此时可以自定义处理逻辑。

2.4.1 自定义序列化器

以下是一个自定义序列化器的示例,用于将Date类型格式化为特定字符串:

java 复制代码
// 自定义Date序列化器
class DateSerializer implements JsonSerializer<Date> {
    private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
    
    @Override
    public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext context) {
        return new JsonPrimitive(dateFormat.format(src));  // 将Date格式化为yyyy-MM-dd字符串
    }
}

// 注册自定义序列化器
Gson gson = new GsonBuilder()
   .registerTypeAdapter(Date.class, new DateSerializer())  // 注册Date类型的序列化器
   .create();

// 创建包含Date字段的类
class Event {
    private String name;
    private Date date;
    
    public Event(String name, Date date) {
        this.name = name;
        this.date = date;
    }
    
    public String getName() { return name; }
    public Date getDate() { return date; }
}

// 测试自定义序列化
Event event = new Event("Conference", new Date());
String jsonEvent = gson.toJson(event);
// 输出结果: {"name":"Conference","date":"2023-10-15"}

源码分析:

  • GsonBuilder在创建Gson实例时,会将注册的TypeAdapter存储在TypeAdapterFactories列表中。
  • 当序列化Event对象时,Gson发现date字段是Date类型,会查找注册的DateSerializer
  • 调用DateSerializerserialize方法,将Date对象转换为格式化的字符串,并封装为JsonPrimitive
2.4.2 自定义反序列化器

以下是一个自定义反序列化器的示例,用于将特定格式的字符串转换为Date对象:

java 复制代码
// 自定义Date反序列化器
class DateDeserializer implements JsonDeserializer<Date> {
    private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
    
    @Override
    public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
            throws JsonParseException {
        try {
            return dateFormat.parse(json.getAsString());  // 将字符串解析为Date对象
        } catch (ParseException e) {
            throw new JsonParseException("Failed to parse date: " + json.getAsString(), e);
        }
    }
}

// 注册自定义反序列化器
Gson gson = new GsonBuilder()
   .registerTypeAdapter(Date.class, new DateDeserializer())  // 注册Date类型的反序列化器
   .create();

// 测试自定义反序列化
String jsonEvent = "{\"name\":\"Conference\",\"date\":\"2023-10-15\"}";
Event event = gson.fromJson(jsonEvent, Event.class);
System.out.println("Event date: " + event.getDate());  // 输出: Event date: Sun Oct 15 00:00:00 GMT 2023

源码分析:

  • 反序列化时,Gson通过JsonDeserializerdeserialize方法将JSON字符串转换为Date对象。
  • JsonDeserializer接口的实现需要处理可能的解析异常,并返回正确的Date对象。

2.5 使用注解控制序列化与反序列化

Gson提供了多种注解来控制序列化和反序列化行为。

2.5.1 @SerializedName注解

@SerializedName注解用于指定JSON属性名与Java字段的映射关系:

java 复制代码
class Product {
    @SerializedName("product_name")  // 指定JSON中的属性名
    private String name;
    
    @SerializedName(value = "price_in_cents", alternate = {"priceInDollars"})  // 指定多个备选属性名
    private int price;
    
    public Product(String name, int price) {
        this.name = name;
        this.price = price;
    }
    
    public String getName() { return name; }
    public int getPrice() { return price; }
}

// 测试@SerializedName注解
Product product = new Product("Laptop", 1200);
Gson gson = new Gson();
String jsonProduct = gson.toJson(product);
// 输出结果: {"product_name":"Laptop","price_in_cents":1200}

// 反序列化时,无论是"price_in_cents"还是"priceInDollars"都能正确映射到price字段
String jsonWithAltName = "{\"product_name\":\"Phone\",\"priceInDollars\":800}";
Product parsedProduct = gson.fromJson(jsonWithAltName, Product.class);
System.out.println("Product price: " + parsedProduct.getPrice());  // 输出: Product price: 800

源码分析:

  • 在序列化和反序列化过程中,Gson会通过反射检查字段上的@SerializedName注解。
  • 对于序列化,使用注解中指定的名称作为JSON属性名;对于反序列化,会尝试匹配所有指定的备选名称。
2.5.2 @Expose注解

@Expose注解用于控制字段是否被序列化或反序列化:

java 复制代码
class UserProfile {
    @Expose  // 该字段会被序列化和反序列化
    private String username;
    
    @Expose(serialize = false)  // 该字段不会被序列化
    private String email;
    
    @Expose(deserialize = false)  // 该字段不会被反序列化
    private int age;
    
    private String password;  // 没有@Expose注解,默认不会被序列化和反序列化
    
    public UserProfile(String username, String email, int age, String password) {
        this.username = username;
        this.email = email;
        this.age = age;
        this.password = password;
    }
    
    // Getter和Setter方法
    public String getUsername() { return username; }
    public String getEmail() { return email; }
    public int getAge() { return age; }
    public String getPassword() { return password; }
}

// 创建Gson实例时启用Expose注解支持
Gson gson = new GsonBuilder()
   .excludeFieldsWithoutExposeAnnotation()  // 只处理有@Expose注解的字段
   .create();

// 测试@Expose注解
UserProfile profile = new UserProfile("john_doe", "john@example.com", 30, "secret");
String jsonProfile = gson.toJson(profile);
// 输出结果: {"username":"john_doe","age":30}

// 反序列化时,email字段不会被设置
String jsonInput = "{\"username\":\"jane_doe\",\"email\":\"jane@example.com\",\"age\":25,\"password\":\"newpass\"}";
UserProfile parsedProfile = gson.fromJson(jsonInput, UserProfile.class);
System.out.println("Email: " + parsedProfile.getEmail());  // 输出: Email: null

源码分析:

  • GsonBuilderexcludeFieldsWithoutExposeAnnotation()方法会设置一个ExclusionStrategy,用于过滤没有@Expose注解的字段。
  • 在序列化和反序列化过程中,Gson会检查每个字段是否有@Expose注解,并根据注解的参数决定是否处理该字段。

三、Gson核心类与架构解析

3.1 Gson类:核心入口与配置

Gson类是使用Gson框架的主要入口点,负责协调序列化和反序列化过程。以下是Gson类的核心功能和源码分析:

3.1.1 Gson类的构造与初始化

Gson类提供了多个构造方法,最常用的是通过GsonBuilder创建:

java 复制代码
public final class Gson {
    // 存储各种类型的TypeAdapter工厂
    private final List<TypeAdapterFactory> factories;
    // 字段命名策略
    private final FieldNamingStrategy fieldNamingStrategy;
    // 排除策略列表
    private final List<ExclusionStrategy> exclusionStrategies;
    // 其他配置参数...
    
    // 私有构造方法,通过GsonBuilder创建实例
    Gson(...) {
        this.factories = factories;
        this.fieldNamingStrategy = fieldNamingStrategy;
        this.exclusionStrategies = exclusionStrategies;
        // 初始化其他配置参数...
    }
    
    // 通过GsonBuilder创建Gson实例的静态方法
    public static GsonBuilder newBuilder() {
        return new GsonBuilder();
    }
    
    // 其他方法...
}

GsonBuilder类用于配置和创建Gson实例,它提供了一系列方法来设置各种参数:

java 复制代码
public final class GsonBuilder {
    // 默认的TypeAdapter工厂列表
    private List<TypeAdapterFactory> factories = new ArrayList<>();
    // 字段命名策略,默认为IDENTITY(保持原字段名)
    private FieldNamingStrategy fieldNamingPolicy = FieldNamingPolicy.IDENTITY;
    // 排除策略列表
    private List<ExclusionStrategy> exclusionStrategies = new ArrayList<>();
    // 其他配置参数...
    
    // 设置字段命名策略的方法
    public GsonBuilder setFieldNamingPolicy(FieldNamingPolicy fieldNamingPolicy) {
        this.fieldNamingPolicy = fieldNamingPolicy;
        return this;
    }
    
    // 注册自定义TypeAdapter的方法
    public <T> GsonBuilder registerTypeAdapter(Type type, Object typeAdapter) {
        // 验证typeAdapter是否为JsonSerializer或JsonDeserializer的实例
        // 将TypeAdapter添加到factories列表
        return this;
    }
    
    // 创建Gson实例的方法
    public Gson create() {
        // 构建最终的TypeAdapter工厂列表
        List<TypeAdapterFactory> factories = buildFactories();
        // 创建并返回Gson实例
        return new Gson(
            factories,
            fieldNamingPolicy,
            exclusionStrategies,
            // 其他参数...
        );
    }
    
    // 构建TypeAdapter工厂列表的私有方法
    private List<TypeAdapterFactory> buildFactories() {
        List<TypeAdapterFactory> factories = new ArrayList<>();
        
        // 添加用户注册的TypeAdapter工厂(优先级最高)
        factories.addAll(this.factories);
        
        // 添加内置的TypeAdapter工厂
        factories.add(TypeAdapters.JSON_ELEMENT_FACTORY);
        factories.add(ObjectTypeAdapter.FACTORY);
        // 添加其他内置工厂...
        
        return Collections.unmodifiableList(factories);
    }
}
3.1.2 Gson类的核心方法

Gson类的核心方法是toJsonfromJson,分别用于序列化和反序列化:

java 复制代码
public final class Gson {
    // 将对象序列化为JSON字符串
    public String toJson(Object src) {
        if (src == null) {
            return toJson(JsonNull.INSTANCE);
        }
        // 获取对象的类型
        Type typeOfSrc = src.getClass();
        // 调用重载的toJson方法
        return toJson(src, typeOfSrc);
    }
    
    // 将对象按照指定类型序列化为JSON字符串
    public String toJson(Object src, Type typeOfSrc) {
        StringWriter writer = new StringWriter();
        // 调用toJson方法,将结果写入StringWriter
        toJson(src, typeOfSrc, writer);
        return writer.toString();
    }
    
    // 将对象按照指定类型序列化为JSON,并写入Writer
    public void toJson(Object src, Type typeOfSrc, Appendable writer) throws JsonIOException {
        try {
            // 创建JsonWriter用于写入JSON
            JsonWriter jsonWriter = newJsonWriter(Streams.writerForAppendable(writer));
            // 序列化对象
            toJson(src, typeOfSrc, jsonWriter);
        } catch (IOException e) {
            throw new JsonIOException(e);
        }
    }
    
    // 将对象按照指定类型序列化为JSON,并写入JsonWriter
    public void toJson(Object src, Type typeOfSrc, JsonWriter writer) throws JsonIOException {
        // 获取处理该类型的TypeAdapter
        TypeAdapter<?> adapter = getAdapter(TypeToken.get(typeOfSrc));
        
        boolean oldLenient = writer.isLenient();
        writer.setLenient(true);
        try {
            // 调用TypeAdapter的write方法进行序列化
            ((TypeAdapter<Object>) adapter).write(writer, src);
        } catch (IOException e) {
            throw new JsonIOException(e);
        } finally {
            writer.setLenient(oldLenient);
        }
    }
    
    // 从JSON字符串反序列化为对象
    public <T> T fromJson(String json, Class<T> classOfT) throws JsonSyntaxException {
        if (json == null) {
            return null;
        }
        // 创建StringReader读取JSON字符串
        StringReader reader = new StringReader(json);
        // 调用重载的fromJson方法
        return fromJson(reader, classOfT);
    }
    
    // 从JSON字符串反序列化为对象(使用TypeToken指定泛型类型)
    public <T> T fromJson(String json, Type typeOfT) throws JsonSyntaxException {
        if (json == null) {
            return null;
        }
        // 创建StringReader读取JSON字符串
        StringReader reader = new StringReader(json);
        // 调用重载的fromJson方法
        return fromJson(reader, typeOfT);
    }
    
    // 从Reader读取JSON并反序列化为对象
    public <T> T fromJson(Reader json, Type typeOfT) throws JsonIOException, JsonSyntaxException {
        // 创建JsonReader用于读取JSON
        JsonReader jsonReader = newJsonReader(json);
        // 调用重载的fromJson方法
        return fromJson(jsonReader, typeOfT);
    }
    
    // 从JsonReader读取JSON并反序列化为对象
    public <T> T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException {
        // 标记是否需要关闭JsonReader
        boolean isEmpty = true;
        boolean oldLenient = reader.isLenient();
        reader.setLenient(true);
        try {
            // 读取JSON开始标记
            reader.peek();
            isEmpty = false;
            // 获取处理该类型的TypeAdapter
            TypeAdapter<?> adapter = getAdapter(TypeToken.get(typeOfT));
            // 调用TypeAdapter的read方法进行反序列化
            T result = (T) adapter.read(reader);
            // 验证JSON是否已完全读取
            assertFullConsumption(reader, typeOfT);
            return result;
        } catch (EOFException e) {
            // 处理空JSON的情况
            if (isEmpty) {
                return null;
            }
            throw new JsonSyntaxException(e);
        } catch (IllegalStateException e) {
            throw new JsonSyntaxException(e);
        } catch (IOException e) {
            throw new JsonIOException(e);
        } catch (AssertionError e) {
            throw new JsonIOException(e);
        } finally {
            reader.setLenient(oldLenient);
        }
    }
    
    // 获取处理指定类型的TypeAdapter
    public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {
        // 从缓存中查找TypeAdapter
        TypeAdapter<?> cached = typeTokenCache.get(type);
        if (cached != null) {
            return (TypeAdapter<T>) cached;
        }
        
        // 缓存未命中,遍历工厂列表查找合适的TypeAdapter
        Map<TypeToken<?>, TypeAdapter<?>> threadCalls = calls.get();
        boolean requiresThreadLocalCleanup = false;
        if (threadCalls == null) {
            threadCalls = new HashMap<>();
            calls.set(threadCalls);
            requiresThreadLocalCleanup = true;
        }
        
        // 检查是否正在处理该类型(防止循环引用)
        TypeAdapter<?> candidate = threadCalls.get(type);
        if (candidate != null) {
            return (TypeAdapter<T>) candidate;
        }
        
        try {
            // 标记正在处理该类型
            threadCalls.put(type, null);
            // 遍历工厂列表查找合适的TypeAdapter
            for (TypeAdapterFactory factory : factories) {
                TypeAdapter<T> candidateAdapter = factory.create(this, type);
                if (candidateAdapter != null) {
                    // 找到合适的TypeAdapter,缓存并返回
                    typeTokenCache.put(type, candidateAdapter);
                    return candidateAdapter;
                }
            }
            throw new IllegalArgumentException("Gson cannot handle " + type);
        } finally {
            // 移除正在处理的标记
            threadCalls.remove(type);
            if (requiresThreadLocalCleanup) {
                calls.remove();
            }
        }
    }
}

3.2 TypeAdapter体系:序列化与反序列化的核心

TypeAdapter是Gson中处理类型序列化和反序列化的核心接口,定义了将Java对象与JSON相互转换的方法。

3.2.1 TypeAdapter接口定义
java 复制代码
public abstract class TypeAdapter<T> {
    // 将Java对象序列化为JSON,并写入JsonWriter
    public abstract void write(JsonWriter out, T value) throws IOException;
    
    // 从JsonReader读取JSON,并反序列化为Java对象
    public abstract T read(JsonReader in) throws IOException;
    
    // 将Java对象转换为JsonElement
    public final JsonElement toJsonTree(T value) {
        try {
            JsonTreeWriter jsonWriter = new JsonTreeWriter();
            write(jsonWriter, value);
            return jsonWriter.get();
        } catch (IOException e) {
            throw new JsonIOException(e);
        }
    }
    
    // 从JsonElement解析为Java对象
    public final T fromJsonTree(JsonElement element) {
        try {
            JsonReader jsonReader = new JsonTreeReader(element);
            return read(jsonReader);
        } catch (IOException e) {
            throw new JsonIOException(e);
        }
    }
    
    // 其他辅助方法...
}
3.2.2 TypeAdapter的实现与注册

Gson提供了多种内置的TypeAdapter实现,例如:

  • StringTypeAdapter:处理String类型的序列化和反序列化
  • NumberTypeAdapter:处理数字类型的序列化和反序列化
  • BooleanTypeAdapter:处理布尔类型的序列化和反序列化
  • CollectionTypeAdapterFactory:处理集合类型的序列化和反序列化
  • MapTypeAdapterFactory:处理映射类型的序列化和反序列化

开发者可以通过GsonBuilderregisterTypeAdapter方法注册自定义的TypeAdapter:

java 复制代码
Gson gson = new GsonBuilder()
   .registerTypeAdapter(MyClass.class, new MyClassTypeAdapter())
   .create();
3.2.3 TypeAdapterFactory:创建TypeAdapter的工厂

TypeAdapterFactory接口用于创建特定类型的TypeAdapter:

java 复制代码
public interface TypeAdapterFactory {
    // 为指定类型创建TypeAdapter
    <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type);
}

Gson内部使用多个TypeAdapterFactory来处理不同类型的序列化和反序列化。例如:

  • ReflectiveTypeAdapterFactory:使用反射处理普通Java对象
  • CollectionTypeAdapterFactory:处理集合类型
  • MapTypeAdapterFactory:处理映射类型
  • EnumTypeAdapterFactory:处理枚举类型

3.3 JsonReader与JsonWriter:JSON解析与生成的基础

JsonReader和JsonWriter是Gson处理JSON数据的底层工具类。

3.3.1 JsonReader:JSON解析器

JsonReader用于从输入流或字符串中读取JSON数据,提供了一系列方法来解析不同类型的JSON元素:

java 复制代码
public final class JsonReader implements Closeable {
    // 构造方法,从Reader读取JSON
    public JsonReader(Reader in) {
        // 初始化解析器状态
    }
    
    // 解析JSON的下一个标记,并返回其类型
    public JsonToken peek() throws IOException {
        // 解析下一个标记并返回类型
    }
    
    // 读取JSON字符串值
    public String nextString() throws IOException {
        // 读取并返回字符串值
    }
    
    // 读取JSON布尔值
    public boolean nextBoolean() throws IOException {
        // 读取并返回布尔值
    }
    
    // 读取JSON null值
    public void nextNull() throws IOException {
        // 读取null值
    }
    
    // 读取JSON数字值
    public double nextDouble() throws IOException {
        // 读取并返回数字值
    }
    
    // 开始解析JSON对象
    public void beginObject() throws IOException {
        // 验证并开始解析对象
    }
    
    // 结束解析JSON对象
    public void endObject() throws IOException {
        // 验证并结束解析对象
    }
    
    // 开始解析JSON数组
    public void beginArray() throws IOException {
        // 验证并开始解析数组
    }
    
    // 结束解析JSON数组
    public void endArray() throws IOException {
        // 验证并结束解析数组
    }
    
    // 读取JSON对象的下一个属性名
    public String nextName() throws IOException {
        // 读取并返回属性名
    }
    
    // 其他解析方法...
}
3.3.2 JsonWriter:JSON生成器

JsonWriter用于将Java对象转换为JSON格式并写入输出流:

java 复制代码
public final class JsonWriter implements Closeable, Flushable {
    // 构造方法,写入到Writer
    public JsonWriter(Writer out) {
        // 初始化写入器状态
    }
    
    // 设置是否允许宽松的JSON格式
    public JsonWriter setLenient(boolean lenient) {
        // 设置宽松模式
        return this;
    }
    
    // 写入JSON null值
    public JsonWriter nullValue() throws IOException {
        // 写入null值
        return this;
    }
    
    // 写入JSON布尔值
    public JsonWriter value(boolean value) throws IOException {
        // 写入布尔值
        return this;
    }
    
    // 写入JSON数字值
    public JsonWriter value(double value) throws IOException {
        // 写入数字值
        return this;
    }
    
    // 写入JSON字符串值
    public JsonWriter value(String value) throws IOException {
        // 写入字符串值
        return this;
    }
    
    // 开始写入JSON对象
    public JsonWriter beginObject() throws IOException {
        // 开始写入对象
        return this;
    }
    
    // 结束写入JSON对象
    public JsonWriter endObject() throws IOException {
        // 结束写入对象
        return this;
    }
    
    // 开始写入JSON数组
    public JsonWriter beginArray() throws IOException {
        // 开始写入数组
        return this;
    }
    
    // 结束写入JSON数组
    public JsonWriter endArray() throws IOException {
        // 结束写入数组
        return this;
    }
    
    // 写入JSON对象的属性名
    public JsonWriter name(String name) throws IOException {
        // 写入属性名
        return this;
    }
    
    // 其他写入方法...
}

四、Gson的序列化流程源码解析

4.1 序列化流程概述

Gson的序列化流程是将Java对象转换为JSON格式的过程,主要涉及以下关键步骤:

  1. 获取对象的类型信息
  2. 查找处理该类型的TypeAdapter
  3. 递归处理对象的各个字段
  4. 使用JsonWriter将数据写入JSON格式

4.2 从toJson方法开始

当调用gson.toJson(object)时,序列化流程正式启动:

java 复制代码
public String toJson(Object src) {
    if (src == null) {
        return toJson(JsonNull.INSTANCE);
    }
    // 获取对象的实际类型
    Type typeOfSrc = src.getClass();
    // 调用重载的toJson方法
    return toJson(src, typeOfSrc);
}

4.3 获取TypeAdapter

Gson通过getAdapter方法获取处理该类型的TypeAdapter:

java 复制代码
public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {
    // 从缓存中查找TypeAdapter
    TypeAdapter<?> cached = typeTokenCache.get(type);
    if (cached != null) {
        return (TypeAdapter<T>) cached;
    }
    
    // 缓存未命中,遍历工厂列表查找合适的TypeAdapter
    // ...
    
    // 遍历工厂列表
    for (TypeAdapterFactory factory : factories) {
        TypeAdapter<T> candidateAdapter = factory.create(this, type);
        if (candidateAdapter != null) {
            // 找到合适的TypeAdapter,缓存并返回
            typeTokenCache.put(type, candidateAdapter);
            return candidateAdapter;
        }
    }
    
    throw new IllegalArgumentException("Gson cannot handle " + type);
}

4.4 对象序列化的反射实现

对于普通Java对象,Gson使用ReflectiveTypeAdapterFactory创建的ReflectiveTypeAdapter进行序列化:

java 复制代码
public final class ReflectiveTypeAdapterFactory implements TypeAdapterFactory {
    // 省略其他方法...
    
    @Override
    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
        Class<? super T> raw = type.getRawType();
        
        // 检查是否为接口或抽象类
        if (!Object.class.isAssignableFrom(raw)) {
            return null; // 无法处理非对象类型
        }
        
        // 获取该类型的所有字段
        Map<String, BoundField> boundFields = getBoundFields(gson, type, raw);
        if (boundFields.isEmpty()) {
            return null;
        }
        
        // 创建并返回ReflectiveTypeAdapter
        return new Adapter<>(type, boundFields);
    }
    
    // 获取所有需要序列化的字段
    private Map<String, BoundField> getBoundFields(
            Gson gson, TypeToken<?> type, Class<?> raw) {
        Map<String, BoundField> result = new LinkedHashMap<>();
        if (raw.isInterface()) {
            return result;
        }
        
        Type declaredType = type.getType();
        // 递归处理父类的字段
        while (raw != Object.class) {
            Field[] fields = raw.getDeclaredFields();
            for (Field field : fields) {
                boolean serialize = excludeField(field, true);
                boolean deserialize = excludeField(field, false);
                if (!serialize && !deserialize) {
                    continue;
                }
                
                // 使私有字段可访问
                field.setAccessible(true);
                Type fieldType = $Gson$Types.resolve(type.getType(), raw, field.getGenericType());
                // 创建BoundField,用于处理字段的序列化和反序列化
                BoundField boundField = createBoundField(
                        gson, field, field.getName(),
                        TypeToken.get(fieldType), serialize, deserialize);
                BoundField previous = result.put(boundField.name, boundField);
                if (previous != null) {
                    throw new IllegalArgumentException(declaredType
                            + " declares multiple JSON fields named " + previous.name);
                }
            }
            // 处理父类
            type = TypeToken.get($Gson$Types.resolve(type.getType(), raw, raw.getGenericSuperclass()));
            raw = type.getRawType();
        }
        return result;
    }
    
    // 创建BoundField的方法
    private BoundField createBoundField(
            final Gson gson, final Field field, final String name,
            final TypeToken<?> fieldType, boolean serialize, boolean deserialize) {
        // 检查字段上是否有@SerializedName注解
        final boolean isPrimitive = Primitives.isPrimitive(fieldType.getRawType());
        // 获取字段的序列化器
        final TypeAdapter<?> typeAdapter = gson.getAdapter(fieldType);
        
        return new BoundField(name, serialize, deserialize) {
            @Override
            void write(JsonWriter writer, Object value)
                    throws IOException, IllegalAccessException {
                // 获取字段的值
                Object fieldValue = field.get(value);
                // 使用TypeAdapter写入字段值
                TypeAdapter<Object> adapter = (TypeAdapter<Object>) typeAdapter;
                adapter.write(writer, fieldValue);
            }
            
            @Override
            void read(JsonReader reader, Object value)
                    throws IOException, IllegalAccessException {
                // 使用TypeAdapter读取字段值
                Object fieldValue = typeAdapter.read(reader);
                if (fieldValue != null || !isPrimitive) {
                    // 设置字段值
                    field.set(value, fieldValue);
                }
            }
            
            @Override
            public boolean writeField(Object value) throws IOException, IllegalAccessException {
                if (!serialize) {
                    return false;
                }
                Object fieldValue = field.get(value);
                return fieldValue != value; // 检查是否为null或自身引用
            }
        };
    }
    
    // ReflectiveTypeAdapter的实现
    static final class Adapter<T> extends TypeAdapter<T> {
        private final Map<String, BoundField> boundFields;
        
        Adapter(TypeToken<T> type, Map<String, BoundField> boundFields) {
            this.boundFields = boundFields;
        }
        
        @Override
        public T read(JsonReader in) throws IOException {
            // 反序列化实现...
        }
        
        @Override
        public void write(JsonWriter out, T value) throws IOException {
            if (value == null) {
                out.nullValue();
                return;
            }
            
            // 开始写入JSON对象
            out.beginObject();
            try {
                for (BoundField boundField : boundFields.values()) {
                    if (boundField.writeField(value)) {
                        // 写入字段名
                        out.name(boundField.name);
                        // 写入字段值
                        boundField.write(out, value);
                    }
                }
            } catch (IllegalAccessException e) {
                throw new AssertionError(e);
            }
            // 结束写入JSON对象
            out.endObject();
        }
    }
}

4.5 集合与映射的序列化

对于集合和映射类型,Gson使用专门的TypeAdapter进行处理:

4.5.1 集合序列化
java 复制代码
public final class CollectionTypeAdapterFactory implements TypeAdapterFactory {
    private final ConstructorConstructor constructorConstructor;
    
    public CollectionTypeAdapterFactory(ConstructorConstructor constructorConstructor) {
        this.constructorConstructor = constructorConstructor;
    }
    
    @Override
    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
        Type type = typeToken.getType();
        
        // 检查是否为集合类型
        Class<? super T> rawType = typeToken.getRawType();
        if (!Collection.class.isAssignableFrom(rawType)) {
            return null;
        }
        
        // 获取集合元素的类型
        Type elementType = $Gson$Types.getCollectionElementType(type, rawType);
        TypeAdapter<?> elementTypeAdapter = gson.getAdapter(TypeToken.get(elementType));
        
        // 创建集合实例的工厂
        ObjectConstructor<T> constructor = constructorConstructor.get(typeToken);
java 复制代码
        // 创建集合类型的TypeAdapter
        return (TypeAdapter<T>) new TypeAdapter<Collection<Object>>() {
            @SuppressWarnings("unchecked")
            @Override
            public Collection<Object> read(JsonReader in) throws IOException {
                // 如果当前标记是JSON NULL,直接返回null
                if (in.peek() == JsonToken.NULL) {
                    in.nextNull();
                    return null;
                }
                // 开始解析JSON数组
                in.beginArray();
                // 使用反射创建集合实例
                Collection<Object> collection = constructor.construct();
                while (in.hasNext()) {
                    // 读取数组中的每个元素,并使用元素类型的TypeAdapter进行反序列化
                    collection.add(elementTypeAdapter.read(in));
                }
                // 结束解析JSON数组
                in.endArray();
                return collection;
            }

            @Override
            public void write(JsonWriter out, Collection<Object> collection) throws IOException {
                if (collection == null) {
                    out.nullValue();
                    return;
                }
                // 开始写入JSON数组
                out.beginArray();
                for (Object element : collection) {
                    // 使用元素类型的TypeAdapter将元素序列化为JSON
                    elementTypeAdapter.write(out, element);
                }
                // 结束写入JSON数组
                out.endArray();
            }
        }.nullSafe();
    }
}

在集合序列化过程中,Gson首先判断集合是否为null,若是则直接写入null。若集合不为null,则开始写入JSON数组的起始符号[,然后遍历集合中的每个元素,通过对应元素类型的TypeAdapter将元素序列化为JSON格式并写入,最后写入JSON数组的结束符号]

4.5.2 映射序列化
java 复制代码
public final class MapTypeAdapterFactory implements TypeAdapterFactory {
    private final ConstructorConstructor constructorConstructor;

    public MapTypeAdapterFactory(ConstructorConstructor constructorConstructor) {
        this.constructorConstructor = constructorConstructor;
    }

    @SuppressWarnings("unchecked")
    @Override
    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
        Type type = typeToken.getType();

        // 检查是否为映射类型
        Class<? super T> rawType = typeToken.getRawType();
        if (!Map.class.isAssignableFrom(rawType)) {
            return null;
        }

        // 获取映射键和值的类型
        Type[] keyAndValueTypes = $Gson$Types.getMapKeyAndValueTypes(type, rawType);
        TypeAdapter<?> keyTypeAdapter = gson.getAdapter(TypeToken.get(keyAndValueTypes[0]));
        TypeAdapter<?> valueTypeAdapter = gson.getAdapter(TypeToken.get(keyAndValueTypes[1]));

        // 创建映射实例的工厂
        ObjectConstructor<T> constructor = constructorConstructor.get(typeToken);

        // 创建映射类型的TypeAdapter
        return (TypeAdapter<T>) new TypeAdapter<Map<Object, Object>>() {
            @SuppressWarnings("unchecked")
            @Override
            public Map<Object, Object> read(JsonReader in) throws IOException {
                if (in.peek() == JsonToken.NULL) {
                    in.nextNull();
                    return null;
                }
                // 开始解析JSON对象
                in.beginObject();
                // 使用反射创建映射实例
                Map<Object, Object> map = constructor.construct();
                while (in.hasNext()) {
                    // 读取键,并使用键类型的TypeAdapter进行反序列化
                    Object key = keyTypeAdapter.read(in);
                    // 读取值,并使用值类型的TypeAdapter进行反序列化
                    Object value = valueTypeAdapter.read(in);
                    map.put(key, value);
                }
                // 结束解析JSON对象
                in.endObject();
                return map;
            }

            @Override
            public void write(JsonWriter out, Map<Object, Object> map) throws IOException {
                if (map == null) {
                    out.nullValue();
                    return;
                }
                // 开始写入JSON对象
                out.beginObject();
                for (Map.Entry<Object, Object> entry : map.entrySet()) {
                    // 使用键类型的TypeAdapter将键序列化为JSON
                    keyTypeAdapter.write(out, entry.getKey());
                    // 使用值类型的TypeAdapter将值序列化为JSON
                    valueTypeAdapter.write(out, entry.getValue());
                }
                // 结束写入JSON对象
                out.endObject();
            }
        }.nullSafe();
    }
}

映射序列化时,Gson先判断映射是否为null,若为null则写入null。若映射不为null,则开始写入JSON对象的起始符号{,接着遍历映射中的每一个键值对,分别通过键类型和值类型对应的TypeAdapter将键和值序列化为JSON格式并写入,最后写入JSON对象的结束符号}

4.6 自定义序列化器的调用

当开发者通过GsonBuilder.registerTypeAdapter注册了自定义的TypeAdapter后,Gson在查找TypeAdapter时,会优先使用自定义的实现。例如,对于自定义的DateSerializer

java 复制代码
class DateSerializer implements JsonSerializer<Date> {
    private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");

    @Override
    public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext context) {
        return new JsonPrimitive(dateFormat.format(src));
    }
}

在序列化包含Date类型字段的对象时,Gson通过getAdapter方法查找处理Date类型的TypeAdapter,由于已经注册了DateSerializer,所以会使用该自定义序列化器。DateSerializerserialize方法将Date对象格式化为指定字符串,并封装为JsonPrimitive返回,然后Gson将其写入JsonWriter,完成该字段的序列化。

五、Gson的反序列化流程源码解析

5.1 反序列化流程概述

Gson的反序列化是将JSON数据转换为Java对象的过程,主要步骤包括:

  1. 从JSON数据源创建JsonReader
  2. 根据目标类型查找对应的TypeAdapter
  3. 使用TypeAdapter解析JSON数据并创建Java对象
  4. 处理嵌套结构和复杂类型

5.2 从fromJson方法开始

当调用gson.fromJson(jsonString, targetType)时,反序列化流程启动:

java 复制代码
public <T> T fromJson(String json, Type typeOfT) throws JsonSyntaxException {
    if (json == null) {
        return null;
    }
    // 创建StringReader读取JSON字符串
    StringReader reader = new StringReader(json);
    // 调用重载的fromJson方法
    return fromJson(reader, typeOfT);
}

public <T> T fromJson(Reader json, Type typeOfT) throws JsonIOException, JsonSyntaxException {
    // 创建JsonReader用于读取JSON
    JsonReader jsonReader = newJsonReader(json);
    // 调用重载的fromJson方法
    return fromJson(jsonReader, typeOfT);
}

public <T> T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException {
    boolean isEmpty = true;
    boolean oldLenient = reader.isLenient();
    reader.setLenient(true);
    try {
        // 检查JSON是否为空
        reader.peek();
        isEmpty = false;
        // 获取处理该类型的TypeAdapter
        TypeAdapter<?> adapter = getAdapter(TypeToken.get(typeOfT));
        // 调用TypeAdapter的read方法进行反序列化
        T result = (T) adapter.read(reader);
        // 确保JSON已完全读取
        assertFullConsumption(reader, typeOfT);
        return result;
    } catch (EOFException e) {
        if (isEmpty) {
            return null;
        }
        throw new JsonSyntaxException(e);
    } catch (IllegalStateException e) {
        throw new JsonSyntaxException(e);
    } catch (IOException e) {
        throw new JsonIOException(e);
    } catch (AssertionError e) {
        throw new JsonIOException(e);
    } finally {
        reader.setLenient(oldLenient);
    }
}

上述代码中,首先创建JsonReader用于读取JSON数据,接着通过getAdapter获取处理目标类型的TypeAdapter,最后调用TypeAdapterread方法将JSON数据转换为Java对象。

5.3 使用反射实现对象反序列化

对于普通Java对象,ReflectiveTypeAdapterread方法负责反序列化:

java 复制代码
static final class Adapter<T> extends TypeAdapter<T> {
    private final Map<String, BoundField> boundFields;

    Adapter(TypeToken<T> type, Map<String, BoundField> boundFields) {
        this.boundFields = boundFields;
    }

    @Override
    public T read(JsonReader in) throws IOException {
        if (in.peek() == JsonToken.NULL) {
            in.nextNull();
            return null;
        }
        // 使用反射创建目标对象实例
        T instance = constructor.construct();
        // 开始解析JSON对象
        in.beginObject();
        while (in.hasNext()) {
            // 读取JSON属性名
            String name = in.nextName();
            // 获取处理该属性的BoundField
            BoundField field = boundFields.get(name);
            if (field != null && field.deserialize) {
                // 使用BoundField的read方法设置对象字段值
                field.read(in, instance);
            } else {
                // 跳过不处理的字段
                in.skipValue();
            }
        }
        // 结束解析JSON对象
        in.endObject();
        return instance;
    }

    @Override
    public void write(JsonWriter out, T value) throws IOException {
        // 序列化实现(前文已分析)
    }
}

在反序列化过程中,ReflectiveTypeAdapter先通过反射创建目标对象实例,然后遍历JSON对象的每个属性,找到对象中与之对应的字段(通过BoundField) ,若字段需要反序列化,则使用BoundFieldread方法,通过对应类型的TypeAdapterJsonReader读取值并设置到对象的字段上;若字段不需要反序列化,则跳过该字段。

5.4 集合与映射的反序列化

5.4.1 集合并反序列化
java 复制代码
public final class CollectionTypeAdapterFactory implements TypeAdapterFactory {
    // 前文已展示部分代码

    @Override
    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
        // 前文已展示部分代码

        return (TypeAdapter<T>) new TypeAdapter<Collection<Object>>() {
            @SuppressWarnings("unchecked")
            @Override
            public Collection<Object> read(JsonReader in) throws IOException {
                if (in.peek() == JsonToken.NULL) {
                    in.nextNull();
                    return null;
                }
                // 开始解析JSON数组
                in.beginArray();
                // 使用反射创建集合实例
                Collection<Object> collection = constructor.construct();
                while (in.hasNext()) {
                    // 读取数组中的每个元素,并使用元素类型的TypeAdapter进行反序列化
                    collection.add(elementTypeAdapter.read(in));
                }
                // 结束解析JSON数组
                in.endArray();
                return collection;
            }

            @Override
            public void write(JsonWriter out, Collection<Object> collection) throws IOException {
                // 序列化实现(前文已分析)
            }
        }.nullSafe();
    }
}

集合反序列化时,先判断JSON数据是否为null,若为null则返回null。若不为null,则开始解析JSON数组,通过反射创建集合实例,然后在遍历数组元素过程中,使用元素类型对应的TypeAdapter将每个JSON元素反序列化为Java对象,并添加到集合中,最后结束数组解析并返回集合。

5.4.2 映射反序列化
java 复制代码
public final class MapTypeAdapterFactory implements TypeAdapterFactory {
    // 前文已展示部分代码

    @Override
    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
        // 前文已展示部分代码

        return (TypeAdapter<T>) new TypeAdapter<Map<Object, Object>>() {
            @SuppressWarnings("unchecked")
            @Override
            public Map<Object, Object> read(JsonReader in) throws IOException {
                if (in.peek() == JsonToken.NULL) {
                    in.nextNull();
                    return null;
                }
                // 开始解析JSON对象
                in.beginObject();
                // 使用反射创建映射实例
                Map<Object, Object> map = constructor.construct();
                while (in.hasNext()) {
                    // 读取键,并使用键类型的TypeAdapter进行反序列化
                    Object key = keyTypeAdapter.read(in);
                    // 读取值,并使用值类型的TypeAdapter进行反序列化
                    Object value = valueTypeAdapter.read(in);
                    map.put(key, value);
                }
                // 结束解析JSON对象
                in.endObject();
                return map;
            }

            @Override
            public void write(JsonWriter out, Map<Object, Object> map) throws IOException {
                // 序列化实现(前文已分析)
            }
        }.nullSafe();
    }
}

映射反序列化时,同样先判断JSON数据是否为null,若为null则返回null。若不为null,则开始解析JSON对象,通过反射创建映射实例,在遍历JSON对象属性过程中,分别使用键类型和值类型对应的TypeAdapter将键和值反序列化为Java对象,并将键值对放入映射中,最后结束对象解析并返回映射。

5.5 自定义反序列化器的调用

以自定义的DateDeserializer为例:

java 复制代码
class DateDeserializer implements JsonDeserializer<Date> {
    private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");

    @Override
    public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
            throws JsonParseException {
        try {
            return dateFormat.parse(json.getAsString());
        } catch (ParseException e) {
            throw new JsonParseException("Failed to parse date: " + json.getAsString(), e);
        }
    }
}

当反序列化包含Date类型字段的JSON数据时,Gson通过getAdapter查找处理Date类型的TypeAdapter,由于注册了DateDeserializer,所以会使用该自定义反序列化器。DateDeserializerdeserialize方法从JsonElement中获取字符串形式的日期数据,然后使用SimpleDateFormat将其解析为Date对象返回,Gson将该对象设置到对应的Java对象字段中,完成反序列化。

六、Gson的注解驱动机制解析

6.1 @SerializedName注解的作用与实现

@SerializedName注解用于指定Java对象字段与JSON属性之间的映射关系,源码层面,Gson在处理字段时会检查该注解:

java 复制代码
class ReflectiveTypeAdapterFactory {
    // 获取所有需要序列化的字段
    private Map<String, BoundField> getBoundFields(
            Gson gson, TypeToken<?> type, Class<?> raw) {
        Map<String, BoundField> result = new LinkedHashMap<>();
        // 遍历类的所有字段
        while (raw != Object.class) {
            Field[] fields = raw.getDeclaredFields();
            for (Field field : fields) {
                SerializedName annotation = field.getAnnotation(SerializedName.class);
                if (annotation != null) {
                    // 使用注解指定的名称作为JSON属性名
                    String name = annotation.value();
                    // 处理备选属性名
                    String[] alternates = annotation.alternate();
                    // 创建BoundField时使用指定的名称
                    BoundField boundField = createBoundField(
                            gson, field, name,
                            TypeToken.get(field.getGenericType()),
                            excludeField(field, true),
                            excludeField(field, false));
                    BoundField previous = result.put(boundField.name, boundField);
                    if (previous != null) {
                        throw new IllegalArgumentException(type + " declares multiple JSON fields named " + previous.name);
                    }
                } else {
                    // 没有注解则使用字段名作为JSON属性名
                    String name = field.getName();
                    // 创建BoundField
                    BoundField boundField = createBoundField(
                            gson, field, name,
                            TypeToken.get(field.getGenericType()),
                            excludeField(field, true),
                            excludeField(field, false));
                    BoundField previous = result.put(boundField.name, boundField);
                    if (previous != null) {
                        throw new IllegalArgumentException(type + " declares multiple JSON fields named " + previous.name);
                    }
                }
            }
            // 处理父类字段
            type = TypeToken.get($Gson$Types.resolve(type.getType(), raw, raw.getGenericSuperclass()));
            raw = type.getRawType();
        }
        return result;
    }
}

在序列化过程中,若字段有@SerializedName注解,Gson使用注解的value属性作为JSON属性名;在反序列化时,Gson会优先尝试使用value属性对应的名称匹配JSON属性,若未找到则尝试alternate属性中的备选名称,从而实现灵活的字段与属性

6.2 @Expose注解的作用与实现

@Expose注解用于控制字段是否参与序列化和反序列化,其实现依赖于GsonBuilder配置的ExclusionStrategy

java 复制代码
public final class GsonBuilder {
    private List<ExclusionStrategy> exclusionStrategies = new ArrayList<>();

    // 启用仅处理带有@Expose注解的字段
    public GsonBuilder excludeFieldsWithoutExposeAnnotation() {
        exclusionStrategies.add(new ExposeAnnotationExclusionStrategy());
        return this;
    }

    // 创建Gson实例
    public Gson create() {
        // 构建最终配置
        return new Gson(
            buildFactories(),
            fieldNamingPolicy,
            exclusionStrategies,
            // 其他参数...
        );
    }
}

// Expose注解的排除策略实现类
class ExposeAnnotationExclusionStrategy implements ExclusionStrategy {
    @Override
    public boolean shouldSkipField(FieldAttributes f) {
        // 检查字段是否有@Expose注解
        Expose exposeAnnotation = f.getAnnotation(Expose.class);
        return exposeAnnotation == null || (!exposeAnnotation.serialize() && !exposeAnnotation.deserialize());
    }

    @Override
    public boolean shouldSkipClass(Class<?> clazz) {
        return false;
    }
}

在序列化和反序列化过程中,Gson会遍历所有字段,并通过ExclusionStrategy判断字段是否应该被处理。如果启用了excludeFieldsWithoutExposeAnnotationExposeAnnotationExclusionStrategy会检查字段是否有@Expose注解:

  • 若没有注解,该字段将被跳过;
  • 若有注解,根据serializedeserialize属性的值,决定该字段是否参与序列化或反序列化。

6.3 @Since和@Until注解的作用与实现

@Since@Until注解用于版本控制,指定字段在哪些版本的API中有效。

java 复制代码
// 自定义排除策略,处理@Since和@Until注解
class VersionExclusionStrategy implements ExclusionStrategy {
    private final double currentVersion;

    public VersionExclusionStrategy(double currentVersion) {
        this.currentVersion = currentVersion;
    }

    @Override
    public boolean shouldSkipField(FieldAttributes f) {
        Since sinceAnnotation = f.getAnnotation(Since.class);
        Until untilAnnotation = f.getAnnotation(Until.class);

        if (sinceAnnotation != null && currentVersion < sinceAnnotation.value()) {
            return true;
        }

        if (untilAnnotation != null && currentVersion >= untilAnnotation.value()) {
            return true;
        }

        return false;
    }

    @Override
    public boolean shouldSkipClass(Class<?> clazz) {
        return false;
    }
}

// 使用示例
Gson gson = new GsonBuilder()
   .setVersion(2.0)
   .addSerializationExclusionStrategy(new VersionExclusionStrategy(2.0))
   .addDeserializationExclusionStrategy(new VersionExclusionStrategy(2.0))
   .create();

在上述代码中,VersionExclusionStrategy根据当前版本号和字段上的@Since@Until注解,决定字段是否参与序列化和反序列化。如果当前版本低于@Since指定的版本,或者当前版本大于等于@Until指定的版本,该字段将被跳过。

七、Gson与Android开发的深度集成

7.1 在网络请求中的应用

在Android开发中,Gson常与网络请求库(如OkHttp、Retrofit)结合使用,用于解析服务器返回的JSON数据。

7.1.1 与Retrofit集成
java 复制代码
// 创建Retrofit实例
Retrofit retrofit = new Retrofit.Builder()
   .baseUrl("https://api.example.com")
   .addConverterFactory(GsonConverterFactory.create())
   .build();

// 创建API接口
interface ApiService {
    @GET("users")
    Call<List<User>> getUsers();
}

// 使用API接口
ApiService apiService = retrofit.create(ApiService.class);
Call<List<User>> call = apiService.getUsers();
call.enqueue(new Callback<List<User>>() {
    @Override
    public void onResponse(Call<List<User>> call, Response<List<User>> response) {
        if (response.isSuccessful()) {
            List<User> users = response.body();
            // 处理数据
        }
    }

    @Override
    public void onFailure(Call<List<User>> call, Throwable t) {
        // 处理错误
    }
});

GsonConverterFactory是Retrofit与Gson集成的关键。它会将服务器返回的JSON数据,通过Gson反序列化为对应的Java对象。

java 复制代码
public final class GsonConverterFactory extends Converter.Factory {
    private final Gson gson;

    private GsonConverterFactory(Gson gson) {
        this.gson = gson;
    }

    // 创建用于反序列化的Converter
    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
        TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
        return new GsonResponseBodyConverter<>(gson, adapter);
    }

    // 创建用于序列化的Converter(通常用于请求体)
    @Override
    public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
        TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
        return new GsonRequestBodyConverter<>(gson, adapter);
    }

    // 创建GsonConverterFactory实例
    public static GsonConverterFactory create() {
        return create(new Gson());
    }

    public static GsonConverterFactory create(Gson gson) {
        return new GsonConverterFactory(gson);
    }
}

GsonResponseBodyConverterGsonRequestBodyConverter分别负责将JSON数据反序列化为Java对象,以及将Java对象序列化为JSON数据。

7.1.2 与OkHttp集成
java 复制代码
OkHttpClient client = new OkHttpClient();

Request request = new Request.Builder()
   .url("https://api.example.com/users")
   .build();

client.newCall(request).enqueue(new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {
        // 处理错误
    }

    @Override
    public void onResponse(Call call, Response response) throws IOException {
        if (response.isSuccessful()) {
            String json = response.body().string();
            Gson gson = new Gson();
            List<User> users = gson.fromJson(json, new TypeToken<List<User>>(){}.getType());
            // 处理数据
        }
    }
});

在OkHttp中,需要手动获取服务器返回的JSON字符串,然后使用Gson进行反序列化。

7.2 在数据存储中的应用

Gson可用于将Java对象序列化为JSON字符串,存储到SharedPreferences或文件中;也可将存储的JSON字符串反序列化为Java对象。

7.2.1 与SharedPreferences集成
java 复制代码
SharedPreferences sharedPreferences = getSharedPreferences("my_prefs", Context.MODE_PRIVATE);
Gson gson = new Gson();

User user = new User("John", 30, true);
String json = gson.toJson(user);

SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("user_data", json);
editor.apply();

String storedJson = sharedPreferences.getString("user_data", "");
User storedUser = gson.fromJson(storedJson, User.class);
7.2.2 与文件存储集成
java 复制代码
File file = new File(getFilesDir(), "data.json");
Gson gson = new Gson();

List<User> users = new ArrayList<>();
users.add(new User("Alice", 25, false));
users.add(new User("Bob", 35, true));

String json = gson.toJson(users);

try (FileWriter writer = new FileWriter(file)) {
    writer.write(json);
} catch (IOException e) {
    e.printStackTrace();
}

try (FileReader reader = new FileReader(file)) {
    List<User> loadedUsers = gson.fromJson(reader, new TypeToken<List<User>>(){}.getType());
} catch (IOException e) {
    e.printStackTrace();
}

八、Gson的性能优化与扩展

8.1 性能优化策略

8.1.1 减少反射使用

反射在序列化和反序列化过程中会带来一定的性能开销。对于频繁使用的类型,可以自定义TypeAdapter,避免反射。

java 复制代码
class UserTypeAdapter extends TypeAdapter<User> {
    @Override
    public void write(JsonWriter out, User value) throws IOException {
        out.beginObject();
        out.name("name").value(value.getName());
        out.name("age").value(value.getAge());
        out.name("isStudent").value(value.isStudent());
        out.endObject();
    }

    @Override
    public User read(JsonReader in) throws IOException {
        String name = null;
        int age = 0;
        boolean isStudent = false;

        in.beginObject();
        while (in.hasNext()) {
            String jsonName = in.nextName();
            switch (jsonName) {
                case "name":
                    name = in.nextString();
                    break;
                case "age":
                    age = in.nextInt();
                    break;
                case "isStudent":
                    isStudent = in.nextBoolean();
                    break;
                default:
                    in.skipValue();
            }
        }
        in.endObject();

        return new User(name, age, isStudent);
    }
}

Gson gson = new GsonBuilder()
   .registerTypeAdapter(User.class, new UserTypeAdapter())
   .create();
8.1.2 启用JVM优化

Gson在JVM环境下可以启用一些优化选项,例如在Android Studio的build.gradle中配置:

groovy 复制代码
android {
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}
8.1.3 复用Gson实例

避免频繁创建Gson实例,因为创建过程涉及初始化各种配置和缓存。建议在应用中使用单例模式管理Gson实例。

java 复制代码
public class GsonSingleton {
    private static volatile Gson instance;

    private GsonSingleton() {}

    public static Gson getInstance() {
        if (instance == null) {
            synchronized (GsonSingleton.class) {
                if (instance == null) {
                    instance = new GsonBuilder()
                       .excludeFieldsWithoutExposeAnnotation()
                       .create();
                }
            }
        }
        return instance;
    }
}

8.2 扩展Gson功能

8.2.1 自定义TypeAdapter

除了前文提到的示例,还可以实现更复杂的TypeAdapter,例如处理包含自定义数据结构的对象。

java 复制代码
class CustomData {
    private List<String> dataList;
    // 构造函数、Getter和Setter方法
}

class CustomDataAdapter extends TypeAdapter<CustomData> {
    @Override
    public void write(JsonWriter out, CustomData value) throws IOException {
        out.beginObject();
        out.name("dataList").beginArray();
        for (String data : value.getDataList()) {
            out.value(data);
        }
        out.endArray();
        out.endObject();
    }

    @Override
    public CustomData read(JsonReader in) throws IOException {
        CustomData customData = new CustomData();
        List<String> dataList = new ArrayList<>();

        in.beginObject();
        while (in.hasNext()) {
            String jsonName = in.nextName();
            if ("dataList".equals(jsonName)) {
                in.beginArray();
                while (in.hasNext()) {
                    dataList.add(in.nextString());
                }
                in.endArray();
            } else {
                in.skipValue();
            }
        }
        in.endObject();

        customData.setDataList(dataList);
        return customData;
    }
}

Gson gson = new GsonBuilder()
   .registerTypeAdapter(CustomData.class, new CustomDataAdapter())
   .create();
8.2.2 自定义TypeAdapterFactory

通过自定义TypeAdapterFactory,可以实现更灵活的类型适配逻辑。

java 复制代码
class CustomTypeAdapterFactory implements TypeAdapterFactory {
    @SuppressWarnings("unchecked")
    @Override
    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
        Class<? super T> rawType = typeToken.getRawType();
        if (rawType == CustomData.class) {
            return (TypeAdapter<T>) new CustomDataAdapter();
        }
        return null;
    }
}

Gson gson = new GsonBuilder()
   .registerTypeAdapterFactory(new CustomTypeAdapterFactory())
   .create();

九、总结与展望

9.1 总结

Gson作为Android开发中处理JSON数据的重要框架,通过简洁的API和强大的功能,极大地简化了Java对象与JSON数据之间的转换过程。通过对其源码的深入分析,我们了解到:

  • 核心架构 :Gson通过Gson类作为入口,利用TypeAdapter体系实现序列化和反序列化,JsonReaderJsonWriter负责底层的JSON解析和生成。
  • 注解驱动 :通过@SerializedName@Expose等注解,实现了灵活的字段控制和版本管理。
  • 集成应用:Gson与Retrofit、OkHttp等网络请求库,以及SharedPreferences、文件存储等数据存储方式深度集成,广泛应用于Android开发的各个环节。
  • 性能与扩展 :通过减少反射使用、复用实例等策略优化性能,并支持自定义TypeAdapterTypeAdapterFactory进行功能扩展。

9.2 展望

随着移动开发技术的不断发展,Gson也面临着新的挑战和机遇:

  • 性能提升:未来可能会进一步优化反射机制,或者引入更高效的代码生成技术,减少序列化和反序列化的性能开销。
  • 功能增强:支持更多的数据格式和复杂的数据结构,提供更强大的注解和配置选项。
  • 兼容性:更好地适应新的Android版本和JVM特性,保持在不同环境下的稳定性和兼容性。
  • 生态融合:与更多的Android开发框架和库进行深度融合,提供更完整的解决方案。

通过持续的优化和扩展,Gson将继续在Android开发中发挥重要作用,为开发者提供高效、可靠的JSON处理能力。

相关推荐
岁忧41 分钟前
(LeetCode 面试经典 150 题 ) 11. 盛最多水的容器 (贪心+双指针)
java·c++·算法·leetcode·面试·go
3Katrina2 小时前
深入理解 useLayoutEffect:解决 UI "闪烁"问题的利器
前端·javascript·面试
coderlin_3 小时前
BI布局拖拽 (1) 深入react-gird-layout源码
android·javascript·react.js
2501_915918413 小时前
Fiddler中文版全面评测:功能亮点、使用场景与中文网资源整合指南
android·ios·小程序·https·uni-app·iphone·webview
wen's5 小时前
React Native安卓刘海屏适配终极方案:仅需修改 AndroidManifest.xml!
android·xml·react native
编程乐学6 小时前
网络资源模板--基于Android Studio 实现的聊天App
android·android studio·大作业·移动端开发·安卓移动开发·聊天app
天天扭码6 小时前
很全面的前端面试——CSS篇(上)
前端·css·面试
爱学习的茄子8 小时前
JavaScript事件循环深度解析:理解异步执行的本质
前端·javascript·面试
没有了遇见8 小时前
Android 通过 SO 库安全存储敏感数据,解决接口劫持问题
android
hsx6668 小时前
使用一个 RecyclerView 构建复杂多类型布局
android