码字不易,请大佬们点点关注,谢谢~
一、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)
方法的执行流程如下:
- Gson实例内部维护了一个
TypeAdapterFactory
列表,用于查找合适的TypeAdapter
处理对象序列化。 - 对于
User
类这种普通Java对象,Gson会使用ReflectiveTypeAdapterFactory
创建一个ReflectiveTypeAdapter
。 ReflectiveTypeAdapter
通过反射获取User
类的所有字段(包括私有字段),并遍历这些字段。- 对于每个字段,根据其类型查找对应的
TypeAdapter
(如String
类型使用StringTypeAdapter
)。 - 调用各字段的
TypeAdapter
的write
方法,将字段值写入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)
方法的执行流程为:
- Gson同样通过
TypeAdapterFactory
列表查找处理User
类的TypeAdapter
,最终找到ReflectiveTypeAdapter
。 - 创建
JsonReader
解析JSON字符串,并将其定位到对象开始处。 ReflectiveTypeAdapter
通过反射创建User
类的实例。- 遍历JSON对象的每个属性,根据属性名查找
User
类中对应的字段。 - 使用字段类型对应的
TypeAdapter
从JsonReader
读取值,并通过反射设置到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
创建处理List
的TypeAdapter
,遍历列表中的每个元素,调用其对应类型的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
创建处理Map
的TypeAdapter
,遍历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
。 - 调用
DateSerializer
的serialize
方法,将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通过
JsonDeserializer
的deserialize
方法将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
源码分析:
GsonBuilder
的excludeFieldsWithoutExposeAnnotation()
方法会设置一个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类的核心方法是toJson
和fromJson
,分别用于序列化和反序列化:
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
:处理映射类型的序列化和反序列化
开发者可以通过GsonBuilder
的registerTypeAdapter
方法注册自定义的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格式的过程,主要涉及以下关键步骤:
- 获取对象的类型信息
- 查找处理该类型的TypeAdapter
- 递归处理对象的各个字段
- 使用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
,所以会使用该自定义序列化器。DateSerializer
的serialize
方法将Date
对象格式化为指定字符串,并封装为JsonPrimitive
返回,然后Gson将其写入JsonWriter
,完成该字段的序列化。
五、Gson的反序列化流程源码解析
5.1 反序列化流程概述
Gson的反序列化是将JSON数据转换为Java对象的过程,主要步骤包括:
- 从JSON数据源创建
JsonReader
- 根据目标类型查找对应的
TypeAdapter
- 使用
TypeAdapter
解析JSON数据并创建Java对象 - 处理嵌套结构和复杂类型
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
,最后调用TypeAdapter
的read
方法将JSON数据转换为Java对象。
5.3 使用反射实现对象反序列化
对于普通Java对象,ReflectiveTypeAdapter
的read
方法负责反序列化:
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
) ,若字段需要反序列化,则使用BoundField
的read
方法,通过对应类型的TypeAdapter
从JsonReader
读取值并设置到对象的字段上;若字段不需要反序列化,则跳过该字段。
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
,所以会使用该自定义反序列化器。DateDeserializer
的deserialize
方法从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
判断字段是否应该被处理。如果启用了excludeFieldsWithoutExposeAnnotation
,ExposeAnnotationExclusionStrategy
会检查字段是否有@Expose
注解:
- 若没有注解,该字段将被跳过;
- 若有注解,根据
serialize
和deserialize
属性的值,决定该字段是否参与序列化或反序列化。
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);
}
}
GsonResponseBodyConverter
和GsonRequestBodyConverter
分别负责将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
体系实现序列化和反序列化,JsonReader
和JsonWriter
负责底层的JSON解析和生成。 - 注解驱动 :通过
@SerializedName
、@Expose
等注解,实现了灵活的字段控制和版本管理。 - 集成应用:Gson与Retrofit、OkHttp等网络请求库,以及SharedPreferences、文件存储等数据存储方式深度集成,广泛应用于Android开发的各个环节。
- 性能与扩展 :通过减少反射使用、复用实例等策略优化性能,并支持自定义
TypeAdapter
和TypeAdapterFactory
进行功能扩展。
9.2 展望
随着移动开发技术的不断发展,Gson也面临着新的挑战和机遇:
- 性能提升:未来可能会进一步优化反射机制,或者引入更高效的代码生成技术,减少序列化和反序列化的性能开销。
- 功能增强:支持更多的数据格式和复杂的数据结构,提供更强大的注解和配置选项。
- 兼容性:更好地适应新的Android版本和JVM特性,保持在不同环境下的稳定性和兼容性。
- 生态融合:与更多的Android开发框架和库进行深度融合,提供更完整的解决方案。
通过持续的优化和扩展,Gson将继续在Android开发中发挥重要作用,为开发者提供高效、可靠的JSON处理能力。