一、Gson反序列化流程概述
1.1 反序列化的基本概念
Gson作为Android开发中常用的JSON处理库,其核心功能之一是将JSON数据转换为Java对象,这个过程称为反序列化(Deserialization)。从JsonReader到Java对象的转换是Gson反序列化的核心路径,涉及多个关键组件和步骤。
1.2 核心组件简介
在深入分析反序列化流程之前,先介绍几个核心组件:
- JsonReader:Gson中用于读取JSON数据的流式API,提供了从各种数据源(如文件、网络流)读取JSON的能力。
- TypeAdapter:Gson的核心适配器接口,负责具体类型的序列化和反序列化逻辑。
- TypeToken:用于捕获泛型类型信息,解决Java泛型擦除问题。
- ObjectConstructor:对象构造器,负责创建Java对象实例。
- FieldNamingStrategy:字段命名策略,处理JSON字段名与Java字段名的映射关系。
1.3 反序列化的整体流程
Gson从JsonReader到Java对象的反序列化整体流程可以概括为:
- 创建Gson实例并配置相关参数。
- 调用Gson的fromJson()方法,传入JsonReader和目标类型。
- Gson根据目标类型查找对应的TypeAdapter。
- 使用找到的TypeAdapter从JsonReader读取JSON数据并转换为Java对象。
- 返回生成的Java对象。
下面我们将深入分析每个步骤的源码实现。
二、Gson实例的创建与配置
2.1 GsonBuilder类的作用
GsonBuilder是用于构建Gson实例的工具类,它允许开发者配置各种参数,如日期格式、字段命名策略、自定义TypeAdapter等。
public final class GsonBuilder {
// 配置参数
private boolean serializeNulls = false;
private boolean complexMapKeySerialization = false;
private boolean generateNonExecutableJson = false;
private boolean escapeHtmlChars = true;
private boolean prettyPrinting = false;
private boolean lenient = false;
private boolean serializeSpecialFloatingPointValues = false;
private LongSerializationPolicy longSerializationPolicy = LongSerializationPolicy.DEFAULT;
private FieldNamingStrategy fieldNamingPolicy = FieldNamingPolicy.IDENTITY;
private Excluder excluder = Excluder.DEFAULT;
private final List<TypeAdapterFactory> factories = new ArrayList<>();
private final List<TypeAdapterFactory> hierarchyFactories = new ArrayList<>();
private String datePattern;
private int dateStyle = DateFormat.DEFAULT;
private int timeStyle = DateFormat.DEFAULT;
// 注册自定义TypeAdapter
public <T> GsonBuilder registerTypeAdapter(Type type, Object typeAdapter) {
// 检查typeAdapter是否为TypeAdapter或JsonSerializer/JsonDeserializer
if (typeAdapter instanceof TypeAdapter<?>) {
// 注册TypeAdapter
factories.add(TypeAdapters.newFactory(TypeToken.get(type), (TypeAdapter<?>) typeAdapter));
} else if (typeAdapter instanceof JsonSerializer<?> || typeAdapter instanceof JsonDeserializer<?>) {
// 注册JsonSerializer/JsonDeserializer
JsonSerializer<?> serializer = typeAdapter instanceof JsonSerializer<?>
? (JsonSerializer<?>) typeAdapter
: null;
JsonDeserializer<?> deserializer = typeAdapter instanceof JsonDeserializer<?>
? (JsonDeserializer<?>) typeAdapter
: null;
factories.add(TypeAdapters.newFactory(TypeToken.get(type), serializer, deserializer));
} else {
throw new IllegalArgumentException("Expected a TypeAdapter, JsonSerializer or JsonDeserializer");
}
return this;
}
// 构建Gson实例
public Gson create() {
// 构建TypeAdapter工厂列表
List<TypeAdapterFactory> factories = new ArrayList<>();
// 添加用户注册的工厂(按注册顺序)
factories.addAll(this.factories);
// 添加内置工厂
factories.add(TypeAdapters.JSON_ELEMENT_FACTORY);
factories.add(ObjectTypeAdapter.FACTORY);
// 添加反射工厂
factories.add(new ReflectiveTypeAdapterFactory(
constructorConstructor,
fieldNamingPolicy,
excluder,
jsonAdapterFactory));
// 创建并返回Gson实例
return new Gson(
factories,
instanceCreators,
serializeNulls,
complexMapKeySerialization,
generateNonExecutableJson,
escapeHtmlChars,
prettyPrinting,
lenient,
serializeSpecialFloatingPointValues,
longSerializationPolicy,
fieldNamingPolicy,
datePattern,
dateStyle,
timeStyle);
}
}
2.2 配置参数的影响
GsonBuilder的各种配置参数会影响反序列化的行为,例如:
- serializeNulls:是否序列化null值,影响JSON中是否包含null字段。
- fieldNamingPolicy:字段命名策略,决定JSON字段名与Java字段名的映射关系。
- datePattern:日期格式,用于解析JSON中的日期字符串。
- excluder:排除策略,控制哪些字段不参与序列化和反序列化。
2.3 Gson实例的初始化
Gson实例在创建时会初始化一系列组件,包括TypeAdapter工厂列表、实例创建器等。
public final class Gson {
// TypeAdapter工厂列表
private final List<TypeAdapterFactory> factories;
// 实例创建器映射
private final Map<Type, InstanceCreator<?>> instanceCreators;
// 其他配置参数
private final boolean serializeNulls;
private final boolean complexMapKeySerialization;
private final boolean generateNonExecutableJson;
private final boolean escapeHtmlChars;
private final boolean prettyPrinting;
private final boolean lenient;
private final boolean serializeSpecialFloatingPointValues;
private final LongSerializationPolicy longSerializationPolicy;
private final FieldNamingStrategy fieldNamingStrategy;
private final String datePattern;
private final int dateStyle;
private final int timeStyle;
// 缓存TypeAdapter的映射
private final Map<TypeToken<?>, TypeAdapter<?>> typeTokenCache = new ConcurrentHashMap<>();
// Gson构造函数
Gson(List<TypeAdapterFactory> factories,
Map<Type, InstanceCreator<?>> instanceCreators,
boolean serializeNulls,
boolean complexMapKeySerialization,
boolean generateNonExecutableJson,
boolean escapeHtmlChars,
boolean prettyPrinting,
boolean lenient,
boolean serializeSpecialFloatingPointValues,
LongSerializationPolicy longSerializationPolicy,
FieldNamingStrategy fieldNamingStrategy,
String datePattern,
int dateStyle,
int timeStyle) {
// 初始化各种配置参数
this.factories = factories;
this.instanceCreators = instanceCreators;
this.serializeNulls = serializeNulls;
this.complexMapKeySerialization = complexMapKeySerialization;
this.generateNonExecutableJson = generateNonExecutableJson;
this.escapeHtmlChars = escapeHtmlChars;
this.prettyPrinting = prettyPrinting;
this.lenient = lenient;
this.serializeSpecialFloatingPointValues = serializeSpecialFloatingPointValues;
this.longSerializationPolicy = longSerializationPolicy;
this.fieldNamingStrategy = fieldNamingStrategy;
this.datePattern = datePattern;
this.dateStyle = dateStyle;
this.timeStyle = timeStyle;
// 初始化构造函数映射
this.constructorConstructor = new ConstructorConstructor(instanceCreators);
}
}
三、JsonReader的工作原理
3.1 JsonReader的基本概念
JsonReader是Gson提供的用于读取JSON数据的流式API,它提供了一种高效、内存友好的方式来处理JSON数据。JsonReader采用拉取式(pull-based)解析模型,允许开发者按需要读取JSON的各个部分。
3.2 JsonReader的核心方法
JsonReader的核心方法包括:
- peek():查看下一个JSON标记的类型,不消耗该标记。
- beginObject():开始解析JSON对象。
- nextName():读取下一个字段名。
- nextString():读取下一个字符串值。
- nextInt():读取下一个整数值。
- nextDouble():读取下一个双精度浮点数值。
- nextBoolean():读取下一个布尔值。
- nextNull():读取null值。
- endObject():结束解析JSON对象。
- beginArray():开始解析JSON数组。
- endArray():结束解析JSON数组。
3.3 JsonReader的内部实现
JsonReader的内部实现基于状态机模型,它维护一个当前状态和一个字符缓冲区,通过读取字符流并解析为JSON标记。
public final class JsonReader implements Closeable {
// 标记类型枚举
public enum JsonToken {
BEGIN_ARRAY,
END_ARRAY,
BEGIN_OBJECT,
END_OBJECT,
NAME,
STRING,
NUMBER,
BOOLEAN,
NULL,
END_DOCUMENT
}
// 当前状态
private int peeked = PEEKED_NONE;
// 字符缓冲区
private final char[] buffer;
private int pos;
private int limit;
// 输入流
private final Reader in;
// 其他状态变量
private String path;
private int[] pathIndices;
private String[] pathNames;
private int pathSize;
// 构造函数
public JsonReader(Reader in) {
if (in == null) {
throw new NullPointerException("in == null");
}
this.in = in;
this.buffer = new char[1024];
this.pathIndices = new int[32];
this.pathNames = new String[32];
}
// 查看下一个标记类型
public JsonToken peek() throws IOException {
int p = peeked;
if (p == PEEKED_NONE) {
p = peeked = doPeek();
}
return JsonToken.values()[p];
}
// 实际执行查看下一个标记类型的方法
private int doPeek() throws IOException {
// 跳过空白字符
int c = nextNonWhitespace(true);
switch (c) {
case -1:
return PEEKED_END_DOCUMENT;
case '{':
// 开始对象
return PEEKED_BEGIN_OBJECT;
case '}':
// 结束对象
return PEEKED_END_OBJECT;
case '[':
// 开始数组
return PEEKED_BEGIN_ARRAY;
case ']':
// 结束数组
return PEEKED_END_ARRAY;
case ':':
// 字段名与值的分隔符
return doPeekName();
case ',':
// 元素分隔符
return doPeekComma();
case '"':
// 字符串
return PEEKED_STRING;
case 't':
// 布尔值true
return PEEKED_BOOLEAN;
case 'f':
// 布尔值false
return PEEKED_BOOLEAN;
case 'n':
// null值
return PEEKED_NULL;
default:
// 数字或其他
if ((c >= '0' && c <= '9') || c == '-') {
return PEEKED_NUMBER;
}
throw syntaxError("Expected value");
}
}
// 读取下一个非空白字符
private int nextNonWhitespace(boolean throwOnEof) throws IOException {
while (true) {
if (pos >= limit) {
// 填充缓冲区
int count = in.read(buffer, 0, buffer.length);
if (count == -1) {
if (throwOnEof) {
throw syntaxError("End of input");
}
return -1;
}
pos = 0;
limit = count;
}
char c = buffer[pos];
if (c <= ' ' && (c == ' ' || c == '\t' || c == '\n' || c == '\r')) {
// 空白字符,跳过
pos++;
continue;
}
return c;
}
}
// 读取下一个字符串
public String nextString() throws IOException {
if (peek() != JsonToken.STRING) {
throw expected(JsonToken.STRING);
}
// 读取字符串值
return readString();
}
// 实际读取字符串的方法
private String readString() throws IOException {
// 处理字符串引号
int c = nextNonWhitespace(true);
if (c != '"') {
throw syntaxError("Expected string");
}
// 读取字符串内容
StringBuilder result = new StringBuilder();
while (true) {
if (pos >= limit) {
// 填充缓冲区
int count = in.read(buffer, 0, buffer.length);
if (count == -1) {
throw syntaxError("Unterminated string");
}
pos = 0;
limit = count;
}
// 查找下一个引号或转义字符
int start = pos;
int end = start;
while (end < limit) {
char c = buffer[end];
if (c == '"') {
// 找到字符串结束
result.append(buffer, start, end - start);
pos = end + 1;
return result.toString();
} else if (c == '\\') {
// 找到转义字符
result.append(buffer, start, end - start);
pos = end + 1;
result.append(readEscapeCharacter());
start = pos;
end = start - 1;
}
end++;
}
// 添加缓冲区内容到结果
result.append(buffer, start, end - start);
pos = end;
}
}
// 其他方法...
}
四、TypeAdapter的查找与创建
4.1 TypeAdapter的角色
TypeAdapter是Gson的核心接口,负责具体类型的序列化和反序列化。它定义了两个核心方法:write()和read()。
public abstract class TypeAdapter<T> {
// 序列化方法:将Java对象转换为JSON
public abstract void write(JsonWriter out, T value) throws IOException;
// 反序列化方法:将JSON转换为Java对象
public abstract T read(JsonReader in) throws IOException;
// 其他辅助方法...
}
4.2 TypeAdapter的查找过程
当Gson需要反序列化一个JSON值时,它会根据目标类型查找对应的TypeAdapter。这个查找过程是通过TypeAdapterFactory链实现的。
public final class Gson {
// 根据类型查找TypeAdapter
public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {
// 先从缓存中查找
TypeAdapter<?> cached = typeTokenCache.get(type);
if (cached != null) {
return (TypeAdapter<T>) cached;
}
// 使用同步块避免重复创建相同类型的TypeAdapter
synchronized (typeTokenCache) {
cached = typeTokenCache.get(type);
if (cached != null) {
return (TypeAdapter<T>) cached;
}
// 从工厂链中查找
TypeAdapter<T> adapter = null;
for (TypeAdapterFactory factory : factories) {
adapter = factory.create(this, type);
if (adapter != null) {
break;
}
}
if (adapter == null) {
throw new IllegalArgumentException("Gson cannot handle " + type);
}
// 缓存找到的TypeAdapter
typeTokenCache.put(type, adapter);
return adapter;
}
}
}
4.3 TypeAdapterFactory的工作机制
TypeAdapterFactory是一个接口,负责创建特定类型的TypeAdapter。
public interface TypeAdapterFactory {
// 为指定类型创建TypeAdapter
<T> TypeAdapter<T> create(Gson gson, TypeToken<T> type);
}
Gson内置了多个TypeAdapterFactory,例如:
- ReflectiveTypeAdapterFactory:使用反射处理普通Java对象。
- CollectionTypeAdapterFactory:处理集合类型。
- MapTypeAdapterFactory:处理Map类型。
- EnumTypeAdapterFactory:处理枚举类型。
- ArrayTypeAdapter:处理数组类型。
4.4 自定义TypeAdapter的注册与使用
开发者可以通过GsonBuilder注册自定义的TypeAdapter,以处理特殊类型或自定义序列化/反序列化逻辑。
// 创建自定义TypeAdapter
public class MyTypeAdapter extends TypeAdapter<MyClass> {
@Override
public void write(JsonWriter out, MyClass value) throws IOException {
// 自定义序列化逻辑
out.beginObject();
out.name("customField").value(value.getCustomField());
out.endObject();
}
@Override
public MyClass read(JsonReader in) throws IOException {
// 自定义反序列化逻辑
MyClass result = new MyClass();
in.beginObject();
while (in.hasNext()) {
String name = in.nextName();
if (name.equals("customField")) {
result.setCustomField(in.nextString());
} else {
in.skipValue();
}
}
in.endObject();
return result;
}
}
// 注册自定义TypeAdapter
Gson gson = new GsonBuilder()
.registerTypeAdapter(MyClass.class, new MyTypeAdapter())
.create();
// 使用自定义TypeAdapter进行反序列化
MyClass obj = gson.fromJson(jsonString, MyClass.class);
五、从JsonReader到Java对象的核心转换过程
5.1 反序列化的入口方法
Gson的反序列化入口方法是fromJson(),它有多个重载版本,最终都会调用到核心的fromJson()方法。
public final class Gson {
// 核心反序列化方法
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
TypeToken<T> typeToken = (TypeToken<T>) TypeToken.get(typeOfT);
TypeAdapter<T> typeAdapter = getAdapter(typeToken);
// 使用TypeAdapter进行反序列化
T object = typeAdapter.read(reader);
// 检查是否所有JSON都已被解析
if (reader.peek() != JsonToken.END_DOCUMENT) {
throw new JsonSyntaxException("Did not consume the entire document.");
}
return object;
} catch (EOFException e) {
/*
* For compatibility with JSON 1.5 and earlier, we return null for empty documents.
*/
if (isEmpty) {
return null;
}
throw new JsonSyntaxException(e);
} catch (IllegalStateException e) {
throw new JsonSyntaxException(e);
} catch (IOException e) {
// IOException wraps underlying java.io.IOException
throw new JsonIOException(e);
} catch (AssertionError e) {
throw new JsonIOException(e);
} finally {
reader.setLenient(oldLenient);
}
}
}
5.2 使用ReflectiveTypeAdapter进行对象反序列化
对于普通Java对象,Gson默认使用ReflectiveTypeAdapter进行反序列化。这个过程涉及反射创建对象实例和设置字段值。
final class ReflectiveTypeAdapterFactory implements TypeAdapterFactory {
private final ConstructorConstructor constructorConstructor;
private final FieldNamingStrategy fieldNamingPolicy;
private final Excluder excluder;
private final JsonAdapterAnnotationTypeAdapterFactory jsonAdapterFactory;
public ReflectiveTypeAdapterFactory(ConstructorConstructor constructorConstructor,
FieldNamingStrategy fieldNamingPolicy, Excluder excluder,
JsonAdapterAnnotationTypeAdapterFactory jsonAdapterFactory) {
this.constructorConstructor = constructorConstructor;
this.fieldNamingPolicy = fieldNamingPolicy;
this.excluder = excluder;
this.jsonAdapterFactory = jsonAdapterFactory;
}
@Override
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
Class<? super T> raw = type.getRawType();
// 检查是否为接口或抽象类
if (!Object.class.isAssignableFrom(raw)) {
return null; // 无法处理的类型
}
// 创建并返回反射类型适配器
return new Adapter<T>(
constructorConstructor.get(type),
getBoundFields(gson, type, raw));
}
// 反射类型适配器实现
public static final class Adapter<T> extends TypeAdapter<T> {
private final ObjectConstructor<T> constructor;
private final Map<String, BoundField> boundFields;
Adapter(ObjectConstructor<T> constructor, Map<String, BoundField> boundFields) {
this.constructor = constructor;
this.boundFields = boundFields;
}
@Override
public T read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
// 创建对象实例
T instance = constructor.construct();
try {
in.beginObject();
while (in.hasNext()) {
// 读取字段名
String name = in.nextName();
// 查找对应的BoundField
BoundField field = boundFields.get(name);
if (field == null || !field.deserialized) {
// 忽略未知字段或不需要反序列化的字段
in.skipValue();
continue;
}
// 读取字段值
field.read(in, instance);
}
in.endObject();
} catch (IllegalStateException e) {
throw new JsonSyntaxException(e);
} catch (IllegalAccessException e) {
throw new AssertionError(e);
}
return instance;
}
// 其他方法...
}
// 绑定字段类
abstract static class BoundField {
final String name;
final boolean serialized;
final boolean deserialized;
protected BoundField(String name, boolean serialized, boolean deserialized) {
this.name = name;
this.serialized = serialized;
this.deserialized = deserialized;
}
// 从JsonReader读取值并设置到对象
abstract void read(JsonReader reader, Object value) throws IOException, IllegalAccessException;
// 其他方法...
}
// 其他方法...
}
5.3 集合和数组的反序列化
对于集合和数组类型,Gson使用专门的TypeAdapter进行反序列化。
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);
// 创建并返回集合类型适配器
@SuppressWarnings({"unchecked", "rawtypes"}) // create() doesn't define a type parameter
TypeAdapter<T> result = new Adapter(gson, elementType, elementTypeAdapter, constructor);
return result;
}
// 集合类型适配器
private static final class Adapter<E> extends TypeAdapter<Collection<E>> {
private final TypeAdapter<E> elementTypeAdapter;
private final ObjectConstructor<? extends Collection<E>> constructor;
public Adapter(Gson context, Type elementType,
TypeAdapter<E> elementTypeAdapter,
ObjectConstructor<? extends Collection<E>> constructor) {
this.elementTypeAdapter =
new TypeAdapterRuntimeTypeWrapper<E>(context, elementTypeAdapter, elementType);
this.constructor = constructor;
}
@Override
public Collection<E> read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
// 创建集合实例
Collection<E> collection = constructor.construct();
// 读取JSON数组
in.beginArray();
while (in.hasNext()) {
// 读取每个元素并添加到集合中
E instance = elementTypeAdapter.read(in);
collection.add(instance);
}
in.endArray();
return collection;
}
// 其他方法...
}
}
5.4 处理嵌套对象和复杂结构
当JSON包含嵌套对象时,Gson会递归地处理每个嵌套层级。
// 嵌套对象示例
public class User {
private String name;
private int age;
private Address address; // 嵌套对象
// getter和setter方法...
}
public class Address {
private String street;
private String city;
private String country;
// getter和setter方法...
}
// 当反序列化User对象时,ReflectiveTypeAdapter会处理嵌套的Address对象
final class ReflectiveTypeAdapterFactory {
// 内部类Adapter的read方法
@Override
public T read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
T instance = constructor.construct();
try {
in.beginObject();
while (in.hasNext()) {
String name = in.nextName();
BoundField field = boundFields.get(name);
if (field == null || !field.deserialized) {
in.skipValue();
continue;
}
// 读取字段值,对于嵌套对象,会递归调用相应的TypeAdapter
field.read(in, instance);
}
in.endObject();
} catch (IllegalStateException e) {
throw new JsonSyntaxException(e);
} catch (IllegalAccessException e) {
throw new AssertionError(e);
}
return instance;
}
}
六、处理特殊情况与高级特性
6.1 处理日期和时间类型
Gson默认支持几种日期格式,但对于特殊格式或自定义需求,需要注册自定义TypeAdapter。
// 日期类型适配器
public class DateTypeAdapter extends TypeAdapter<Date> {
private final DateFormat dateFormat;
public DateTypeAdapter(String pattern) {
this.dateFormat = new SimpleDateFormat(pattern, Locale.US);
}
@Override
public void write(JsonWriter out, Date value) throws IOException {
if (value == null) {
out.nullValue();
return;
}
// 将日期格式化为字符串
String dateString = dateFormat.format(value);
out.value(dateString);
}
@Override
public Date read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
try {
// 从字符串解析日期
String dateString = in.nextString();
return dateFormat.parse(dateString);
} catch (ParseException e) {
throw new JsonSyntaxException(e);
}
}
}
// 注册日期类型适配器
Gson gson = new GsonBuilder()
.registerTypeAdapter(Date.class, new DateTypeAdapter("yyyy-MM-dd"))
.create();
6.2 处理多态类型
当处理多态类型时,需要在JSON中保留类型信息,以便在反序列化时能够正确还原对象类型。
// 基类
public abstract class Shape {
private String color;
public Shape(String color) {
this.color = color;
}
// getter和setter方法...
}
// 子类
public class Circle extends Shape {
private double radius;
public Circle(String color, double radius) {
super(color);
this.radius = radius;
}
// getter和setter方法...
}
// 子类
public class Rectangle extends Shape {
private double width;
private double height;
public Rectangle(String color, double width, double height) {
super(color);
this.width = width;
this.height = height;
}
// getter和setter方法...
}
// 多态类型适配器
public class ShapeTypeAdapter extends TypeAdapter<Shape> {
private static final String TYPE_FIELD = "type";
private static final String DATA_FIELD = "data";
@Override
public void write(JsonWriter out, Shape value) throws IOException {
if (value == null) {
out.nullValue();
return;
}
out.beginObject();
// 写入类型信息
if (value instanceof Circle) {
out.name(TYPE_FIELD).value("circle");
} else if (value instanceof Rectangle) {
out.name(TYPE_FIELD).value("rectangle");
}
// 写入对象数据
out.name(DATA_FIELD);
Gson gson = new Gson();
gson.toJson(value, value.getClass(), out);
out.endObject();
}
@Override
public Shape read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
Gson gson = new Gson();
Class<? extends Shape> type = null;
in.beginObject();
while (in.hasNext()) {
String name = in.nextName();
if (name.equals(TYPE_FIELD)) {
String typeValue = in.nextString();
if ("circle".equals(typeValue)) {
type = Circle.class;
} else if ("rectangle".equals(typeValue)) {
type = Rectangle.class;
}
} else if (name.equals(DATA_FIELD)) {
if (type != null) {
return gson.fromJson(in, type);
} else {
in.skipValue();
}
} else {
in.skipValue();
}
}
in.endObject();
return null;
}
}
6.3 处理自定义序列化和反序列化逻辑
通过注册自定义TypeAdapter,可以实现复杂的序列化和反序列化逻辑。
// 自定义类
public class Money {
private double amount;
private String currency;
public Money(double amount, String currency) {
this.amount = amount;
this.currency = currency;
}
// getter和setter方法...
}
// 自定义TypeAdapter
public class MoneyTypeAdapter extends TypeAdapter<Money> {
@Override
public void write(JsonWriter out, Money value) throws IOException {
if (value == null) {
out.nullValue();
return;
}
// 自定义序列化逻辑:将金额和货币组合成一个字符串
out.value(value.getAmount() + " " + value.getCurrency());
}
@Override
public Money read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
// 自定义反序列化逻辑:从字符串解析金额和货币
String value = in.nextString();
String[] parts = value.split(" ");
if (parts.length == 2) {
try {
double amount = Double.parseDouble(parts[0]);
String currency = parts[1];
return new Money(amount, currency);
} catch (NumberFormatException e) {
throw new JsonSyntaxException("Invalid money format: " + value);
}
} else {
throw new JsonSyntaxException("Invalid money format: " + value);
}
}
}
// 注册自定义TypeAdapter
Gson gson = new GsonBuilder()
.registerTypeAdapter(Money.class, new MoneyTypeAdapter())
.create();
七、性能优化与最佳实践
7.1 反序列化性能考量
Gson的反序列化性能受多种因素影响,包括:
- 反射开销:使用反射创建对象和设置字段值会带来一定的性能开销。
- TypeAdapter的选择:不同的TypeAdapter实现有不同的性能特点,直接操作流的适配器通常比基于JsonTree的适配器性能更好。
- 数据结构复杂度:复杂的数据结构和嵌套层级会增加处理时间。
7.2 性能优化建议
- 重用Gson实例:Gson实例是线程安全的,可以在多个线程中共享和重用。
- 注册自定义TypeAdapter:对于性能敏感的类型,使用自定义TypeAdapter可以避免反射开销。
- 避免使用JsonTree:直接操作JsonReader和JsonWriter的TypeAdapter通常比基于JsonTree的适配器性能更好。
- 使用@Expose注解:通过@Expose注解和
excludeFieldsWithoutExposeAnnotation()方法,只处理需要序列化和反序列化的字段。 - 优化数据结构:简化JSON数据结构,减少嵌套层级,可以提高处理速度。
7.3 常见问题与解决方案
- 空值处理:确保TypeAdapter正确处理null值,避免NullPointerException。
- 类型转换异常:在反序列化时,确保正确处理各种可能的JSON格式,避免类型转换异常。
- 循环引用:处理嵌套对象时,注意避免循环引用导致的StackOverflowError。
- 线程安全:如果TypeAdapter在多线程环境中使用,确保其是线程安全的。
八、总结与展望
8.1 Gson反序列化机制的优势
Gson从JsonReader到Java对象的反序列化机制具有以下优势:
- 灵活性:通过自定义TypeAdapter,可以处理各种复杂的JSON结构和数据类型。
- 可扩展性:通过TypeAdapterFactory机制,可以轻松扩展Gson的功能。
- 性能优化空间:通过选择合适的TypeAdapter和优化策略,可以实现高性能的JSON处理。
- 易用性:简单的API设计使得开发者可以快速上手并实现基本的JSON处理功能。
8.2 未来发展方向
随着Android和Java技术的不断发展,Gson的反序列化机制可能会在以下方向发展:
- Kotlin协程支持:更好地支持Kotlin协程,提供异步反序列化能力。
- 编译时代码生成:引入编译时代码生成技术,减少运行时反射开销。
- 多平台支持:在Kotlin Multiplatform项目中提供更统一的反序列化机制。
- 性能优化:继续优化反序列化性能,特别是在处理大型JSON数据时。
- 简化API:提供更简洁、易用的API,降低开发者的使用门槛。
通过不断改进和扩展,Gson的反序列化机制将继续为开发者提供高效、灵活的JSON处理解决方案。