This article has included AndroidFamily , technical and workplace issues, please pay attention to the public account [Peng Xurui] to ask questions.
foreword
Hello everyone, I am Xiao Peng.
Gson is a Java Json parsing library launched by Google. It has the advantages of low access cost, convenient use, and good function scalability. Everyone must be familiar with it. In this article, we will discuss the basic usage of Gson and the source code analysis of the main process.
Xiaopeng's Android communication group 02 has been established, scan the QR code at the end of the article to enter~
Learning Roadmap:
1. Basic usage of Gson
Gradle 依赖
dependencies {
implementation 'com.google.code.gson:gson:2.10'
}
1.1 GsonBuilder configuration items
The Gson class is the core API of the entire library, and before any serialization or deserialization, we need to obtain a Gson object. You can directly create a default configured Gson object with new, or use the GsonBuilder constructor to configure a Gson object.
In fact, a Gson object represents a Gson working environment, and configurations and caches between different Gson objects will not be reused. Therefore, it is necessary to provide a global Gson object in the common layer in the project, which is not only conducive to unified serialization configuration, but also the basic guarantee for Gson performance optimization.
GsonBuilder 使用示例
Gson gson = new GsonBuilder()
// 设置自定义解析(不支持协变)
.registerTypeAdapter(Id.class, new IdTypeAdapter())
// 设置自定义解析(支持协变)
registerTypeHierarchyAdapter(List.class, new MyListTypeAdapter())
// 设置自定义解析(以工厂方式)
.registerTypeAdapterFactory(new IdTypeAdapterFactory())
// 设置日期格式
.setDateFormat("yyyy-MM-dd HH:mm:ss:SSS")
// 设置自动切换命名风格规则(默认不切换命名风格)
.setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
// 设置过滤指定字段标识符(默认只过滤 transient 和 static 字段)
.excludeFieldsWithModifiers(Modifier.TRANSIENT | Modifier.STATIC)
// 设置类或字段过滤规则
.setExclusionStrategies(new MyExclusionStrategy1())
// 设置过滤规则(只适用于序列化)
.addSerializationExclusionStrategy(new MyExclusionStrategy2())
// 设置过滤规则(只适用于反序列化)
.addDeserializationExclusionStrategy(new MyExclusionStrategy3())
// 设置序列化版本号
.setVersion(1.0)
// 启用非基础类型 Map Key
.enableComplexMapKeySerialization()
// 启用不过滤空值(默认会过滤空值)
.serializeNulls()
// 启用 Json 格式化
.setPrettyPrinting()
.create();
1.2 Annotation configuration
Gson has no compile-time processing, so annotations are runtime annotations.
- @SerializedName field alias: supports setting multiple aliases,
value
variables are valid during serialization and deserialization, andalternate
variables only compatible during deserialization; - @Expose fields are exposed:
- By default, all fields in a class will be exposed, but after using the @Expose annotation, only the fields that declare the annotation will be exposed;
- Annotated
serialize
variables ordeserialize
variables can declare that fields only participate in serialization or deserialization, and both participate by default.
- @JsonAdapter annotation: declared on a specific class or field, used to set TypeAdapter in a more granular manner, with a higher priority than registerTypeAdapter;
- @Since annotation: Declare on a specific class or field, declare the initial serialized version of the field;
- @Until annotation: Declared on a concrete class or field, declares the terminated serialized version of the field. When the serialized version of the field satisfies since ≥ GsonBuilder#setVersion and GsonBuilder#setVersion ≤ until, it will participate in serialization;
1.3 JsonSerializer and JsonDeserializer custom parsing
JsonSerializer
and JsonDeserializer
are custom parsing APIs provided by Gson version 1.x, which are tree-based parsing APIs. When parsing data, they will parse Json data into a JsonElement
tree . JsonElement represents a node on the Json tree, and has 4 specific types:
JsonElement | describe |
---|---|
JsonObject | {} object |
JsonArray | [] array |
JsonPrimitive | basic type |
JsonNull | null value |
1.4 TypeAdapter custom analysis
TypeAdapter
It is a new custom parsing API added by Gson 2.0, and it is an API based on a streaming structure. In fact, JsonSerializer and JsonDeserializer will also end up being constructed as TreeTypeAdapter
;
In comparison, JsonSerializer & JsonDeserializer are relatively convenient, but more memory-intensive. The TypeAdapter is more memory-efficient, but less convenient. However, if you need to use a complete data structure (such as parsing data according to different types according to the type field), you can also manually parse it into a tree structure. Therefore, the TypeAdapter API has a higher priority.
TypeAdapter | JsonSerializer、JsonDeserializer | |
---|---|---|
import version | 2.0 | 1.x |
Stream API | support | not support |
Tree API | Support, can be converted manually | support |
memory usage | Small | Larger than TypeAdapter |
efficiency | high | Lower than TypeAdapter |
Scope of action | Serialization + deserialization | serialization / deserialization |
1.5 The difference between registerTypeAdapter and registerTypeHierarchyAdapter
- registerTypeAdapter is invariant: it will only work on registered types. For example, registration
<List.class,TypeAdapter>
will only affect the fields ofList
the type , but not the fields of the ArrayList type; - registerTypeHierarchyAdapter is covariant: it works on the registered type and its subclasses. For example, registration
<List.class,TypeAdapter>
will only affectList
fieldsArrayList
of type ;
registerTypeAdapter | registerTypeHierarchyAdapter | |
---|---|---|
supports generics | yes | no |
support inheritance | no | yes |
2. Gson source code analysis
In this section, let's analyze the working principle and source code of Gson's core process.
2.1 Talk about the working process of Gson parsing
"TypeAdapter" is an important role in Gson parsing. Every time Gson parses an object type, it first needs to create a TypeAdapter object, and then all parsing work will be handed over to the TypeAdapter#write and TypeAdapter#read methods;
The TypeAdapter object of the Java Bean type is created by the "ReflectiveTypeAdapterFactory" . Every time you create a type of TypeAdapter, you need to recursively use "reflection" to traverse all fields, and parse the annotations on the fields to generate <serializeName - BoundFiled>
a mapping table.
- When serializing, first use reflection to get the field value, and then use
BoundFiled
the serialization ; - When deserializing, first create an object instance (how to create it will be discussed below), then use
BoundField
the deserialization as the value of the field type, and then assign a value to the field through reflection.
Since the writing and reading of field values are performed through Field
metadata reflection, private fields can also be manipulated.
When constructing the Gson object, a series of TypeAdapter creation factories have been initialized, and developers can register custom TypeAdapters:
Gson.java
Gson(final Excluder excluder, ...) {
List<TypeAdapterFactory> factories = new ArrayList<TypeAdapterFactory>();
// built-in type adapters that cannot be overridden
factories.add(TypeAdapters.JSON_ELEMENT_FACTORY);
factories.add(ObjectTypeAdapter.FACTORY);
// 过滤规则
factories.add(excluder);
// 自定义 TypeAdapter
factories.addAll(factoriesToBeAdded);
// 1. 基础类型
factories.add(TypeAdapters.STRING_FACTORY);
factories.add(TypeAdapters.INTEGER_FACTORY);
...
// 2. 复合类型
// 2.1 列表类型
factories.add(new CollectionTypeAdapterFactory(constructorConstructor));
// 2.2 集合类型
factories.add(new MapTypeAdapterFactory(constructorConstructor, complexMapKeySerialization));
this.jsonAdapterFactory = new JsonAdapterAnnotationTypeAdapterFactory(constructorConstructor);
factories.add(jsonAdapterFactory);
// 2.3 枚举类型
factories.add(TypeAdapters.ENUM_FACTORY);
// 2.4 Java Bean 类型
factories.add(new ReflectiveTypeAdapterFactory(constructorConstructor, fieldNamingStrategy, excluder, jsonAdapterFactory));
}
Find the matching TypeAdapter method through Gson#getAdapter:
Gson.java
// TypeAdapter 缓存映射表 <Type - TypeAdapter>
private final Map<TypeToken<?>, TypeAdapter<?>> typeTokenCache = new ConcurrentHashMap<TypeToken<?>, TypeAdapter<?>>();
public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {
// 先从映射表缓存中查找
TypeAdapter<?> cached = typeTokenCache.get(type);
if (cached != null) {
return (TypeAdapter<T>) cached;
}
// 再通过 TypeAdapter 创建工厂创建,并加入映射表缓存中
for (TypeAdapterFactory factory : factories) {
// 从前到后线性扫描创建工厂,找到合适的 TypeAdapter
TypeAdapter<T> candidate = factory.create(this, type);
if (candidate != null) {
// 加入缓存中
typeTokenCache.put(type, candidate);
return candidate;
}
}
}
Create TypeAdapter objects for each type using the ReflectiveTypeAdapterFactory factory:
ReflectiveTypeAdapterFactory.java
// 1. 创建 TypeAdapter 对象
@Override
public <T> TypeAdapter<T> create(Gson gson, final TypeToken<T> type) {
Class<? super T> raw = type.getRawType();
// 检查是否为 Object 类型
if (!Object.class.isAssignableFrom(raw)) {
return null; // it's a primitive!
}
// 1.1 获取对象构造器(下文分析)
ObjectConstructor<T> constructor = constructorConstructor.get(type);
// 1.2 getBoundFields:解析每个字段的适配器
// 1.3 FieldReflectionAdapter:TypeAdapter 对象(Adapter 类型)
return new FieldReflectionAdapter<T>(constructor, getBoundFields(gson, type, raw));
}
public static abstract class Adapter<T, A> extends TypeAdapter<T> {
final Map<String, BoundField> boundFields;
// 2. 反序列化过程
@Override
public T read(JsonReader in) {
// 2.1 创建对象
T instance = constructor.construct();
// 2.2 消费 {
in.beginObject();
// 2.3 递归反序列化每个字段
while (in.hasNext()) {
String name = in.nextName();
BoundField field = boundFields.get(name);
if (field == null || !field.deserialized) {
in.skipValue();
} else {
// 读取流并设置到 instance 对象中
readIntoField(in, instance);
}
}
// 2.4 消费 }
in.endObject();
return instance;
}
// 3. 序列化过程
@Override
public void write(JsonWriter out, T value) {
// 3.1 写入 {
out.beginObject();
// 3.2 递归序列化每个字段
for (BoundField boundField : boundFields.values()) {
// 将对象的每个字段写入流中
boundField.write(out, value);
}
// 3.3 写入 }
out.endObject();
}
}
// -> 1.2 getBoundFields:解析每个字段的适配器
private Map<String, BoundField> getBoundFields(Gson context, TypeToken<?> type, Class<?> raw, boolean blockInaccessible, boolean isRecord) {
// 1.2.1 映射表
Map<String, BoundField> result = new LinkedHashMap<>();
if (raw.isInterface()) {
return result;
}
...
// 1.2.2 遍历所有 Field
Field[] fields = raw.getDeclaredFields();
for (Field field : fields) {
// 1.2.2.1 字段过滤
boolean serialize = includeField(field, true);
boolean deserialize = includeField(field, false);
if (!serialize && !deserialize) {
continue;
}
// 1.2.2.2 获取字段的所有别名,第 0 位是主名称
List<String> fieldNames = getFieldNames(field);
// 1.2.2.3 为所有字段别名创建 BoundField 对象
for (int i = 0, size = fieldNames.size(); i < size; ++i) {
String name = fieldNames.get(i);
// serialize = false 这一行说明:序列化时是采用字段的主名称
if (i != 0) serialize = false;
BoundField boundField = createBoundField(context, field, accessor, name, TypeToken.get(fieldType), serialize, deserialize, blockInaccessible);
BoundField replaced = result.put(name, boundField);
if (previous == null) previous = replaced;
}
// 1.2.2.4 存在两个的字段使用相同 serializeName 的冲突
if (previous != null) {
throw new IllegalArgumentException(declaredType + " declares multiple JSON fields named " + previous.name);
}
}
// 1.2.3 返回映射表
return result;
}
// -> 1.2.2.3 为所有字段别名创建 BoundField 对象
private ReflectiveTypeAdapterFactory.BoundField createBoundField(
final Gson context, final Field field, final String name,
final TypeToken<?> fieldType, boolean serialize, boolean deserialize) {
// 基本类型
final boolean isPrimitive = Primitives.isPrimitive(fieldType.getRawType());
// @JsonAdapter 注解
JsonAdapter annotation = field.getAnnotation(JsonAdapter.class);
TypeAdapter<?> mapped = null;
if (annotation != null) {
mapped = jsonAdapterFactory.getTypeAdapter(constructorConstructor, context, fieldType, annotation);
}
final boolean jsonAdapterPresent = mapped != null;
if (mapped == null) mapped = context.getAdapter(fieldType);
final TypeAdapter<?> typeAdapter = mapped;
return new ReflectiveTypeAdapterFactory.BoundField(name, serialize, deserialize) {
@Override
void write(JsonWriter writer, Object value) {
if (!serialized) return;
// 通过反射读取字段值
Object fieldValue = field.get(value);
TypeAdapter t = jsonAdapterPresent ? typeAdapter : new TypeAdapterRuntimeTypeWrapper(context, typeAdapter, fieldType.getType());
// 写出到流
t.write(writer, fieldValue);
}
@Override
void readIntoField(JsonReader reader, Object target) {
// 从流读取
Object fieldValue = typeAdapter.read(reader);
// 通过反射写入字段值
field.set(target, fieldValue);
}
};
}
2.2 How are container types such as List & Set & Map parsed?
- 1. In the preset container TypAdapter, the container constructor will be
RawType
obtained , and thenelementType
the element type TypeAdapter will be obtained according to the generic argument; - 2. When serializing, first write [left square brackets, then use the TypeAdapter of the element type to serialize element objects in turn, and then write ] right square brackets;
- 3. When deserializing, first create a collection object, and then use the TypeAdapter of the element type to deserialize the element objects in turn;
- 4. The Map type needs to maintain two TypeAdapters, Key and Value.
CollectionTypeAdapterFactory.java
// 1. 创建 TypeAdapter
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;
}
// 1.1 解析元素类型
Type elementType = $Gson$Types.getCollectionElementType(type, rawType);
// 1.2 查找元素类型映射的 TypeAdapter
TypeAdapter<?> elementTypeAdapter = gson.getAdapter(TypeToken.get(elementType));
// 1.3 解析容器对象的构造器
ObjectConstructor<T> constructor = constructorConstructor.get(typeToken);
// 1.4 包装新的 TypeAdapter
TypeAdapter<T> result = new Adapter(gson, elementType, elementTypeAdapter, constructor);
}
private static final class Adapter<E> extends TypeAdapter<Collection<E>> {
// 2. 反序列化过程
@Override
public Collection<E> read(JsonReader in) {
// 2.1 创建容器对象
Collection<E> collection = constructor.construct();
// 2.2 消费 [
in.beginArray();
// 2.3 使用 1.2 步骤的 TypeAdapter 反序列化每个元素
while (in.hasNext()) {
E instance = elementTypeAdapter.read(in);
collection.add(instance);
}
// 2.4 消费 ]
in.endArray();
return collection;
}
// 3. 序列化过程
@Override
public void write(JsonWriter out, Collection<E> collection) {
// 3.1 写入 [
out.beginArray();
// 3.2 使用 1.2 步骤的 TypeAdapter 序列化每个元素
for (E element : collection) {
elementTypeAdapter.write(out, element);
}
// 3.3 写入 ]
out.endArray();
}
}
2.3 How is the enumerated type parsed?
- 1. In the preset EnumTypeAdapter adapter, the entire enumeration list of the enumeration type will be obtained first, and two mapping tables will be generated.
- <name - enumeration> mapping table
- <enum-name> mapping table
- 2. When serializing, the name of the enumeration will be written. When deserializing, the enumeration object will be queried according to the name.
TypeAdapters.java
private static final class EnumTypeAdapter<T extends Enum<T>> extends TypeAdapter<T> {
// <name - 枚举> 映射表
private final Map<String, T> nameToConstant = new HashMap<String, T>();
// <枚举 - name> 映射表
private final Map<T, String> constantToName = new HashMap<T, String>();
public EnumTypeAdapter(Class<T> classOfT) {
for (T constant : classOfT.getEnumConstants()) {
String name = constant.name()
nameToConstant.put(name, constant);
constantToName.put(constant, name);
}
}
@Override
public T read(JsonReader in) {
return nameToConstant.get(in.nextString());
}
@Override
public void write(JsonWriter out, T value) {
out.value(constantToName.get(value));
}
}
2.4 Will nesting of the same type cause infinite recursion?
ReflectiveTypeAdapterFactory
When creating an object's TypeAdapter adapter, it is necessary to recursively create a TypeAdapter for each field. If the type of the field happens to be the same as the type of the class, it will trigger the creation of an identical TypeAdapter, causing infinite recursion. For example:
无限递归的例子
public class Article {
public Article linkedArticle;
}
The analysis found that infinite recursion only occurs when a TypeAdapter of a Java Bean type is created for the first time, and it will be obtained from the cache next time, and infinite recursion will not occur. Therefore, Gson's approach is:
- 1. Before creating a new TypeAdapter each time, create a
FutureTypeAdapter
proxy . After creating the real TypeAdapter, inject it into the proxy object. In this way, when recursively obtaining the TypeAdapter of the field, the proxy object will be obtained instead of recreating the TypeAdapter, thus solving the recursion problem; - 2. In addition, considering that in a multi-threaded environment, the addition and removal of temporary mapping tables will have concurrency issues, so Gson's strategy is to use temporary mapping tables that
ThreadLocal
isolate each thread.
Gson.java
// 线程隔离的映射表
private final ThreadLocal<Map<TypeToken<?>, FutureTypeAdapter<?>>> calls = new ThreadLocal<Map<TypeToken<?>, FutureTypeAdapter<?>>>();
// 线程共享的映射表(基于 ConrurrentHashMap)
private final Map<TypeToken<?>, TypeAdapter<?>> typeTokenCache = new ConcurrentHashMap<TypeToken<?>, TypeAdapter<?>>();
public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {
// 1. 尝试从缓存获取
TypeAdapter<?> cached = typeTokenCache.get(type);
if (cached != null) {
return (TypeAdapter<T>) cached;
}
// 2. 初始化当前线程的临时映射表
Map<TypeToken<?>, FutureTypeAdapter<?>> threadCalls = calls.get();
boolean requiresThreadLocalCleanup = false;
if (threadCalls == null) {
threadCalls = new HashMap<TypeToken<?>, FutureTypeAdapter<?>>();
calls.set(threadCalls);
requiresThreadLocalCleanup = true;
}
// 3. 尝试从临时映射表获取(递归调用时,会从这里获取到代理 TypeAdapter,而不会走到下面的 factory.create
FutureTypeAdapter<T> ongoingCall = (FutureTypeAdapter<T>) threadCalls.get(type);
if (ongoingCall != null) {
return ongoingCall;
}
try {
// 4.1 创建代理 TypeAdapter
FutureTypeAdapter<T> call = new FutureTypeAdapter<T>();
threadCalls.put(type, call);
for (TypeAdapterFactory factory : factories) {
// 4.2 创建 TypeAdapter
TypeAdapter<T> candidate = factory.create(this, type);
// 4.3 将真实的 TypeAdapter 注入到代理 TypeAdapter 中
if (candidate != null) {
call.setDelegate(candidate);
// 4.4 将 TypeAdapter 写入缓存
typeTokenCache.put(type, candidate);
return candidate;
}
}
} finally {
// 5. 清除临时映射表
threadCalls.remove(type);
if (requiresThreadLocalCleanup) {
calls.remove();
}
}
}
2.5 How does Gson create objects?
- 1. Basic types: Integer, Calendar and other basic types have a fixed TypeAdapter, which will create objects through the new keyword;
- 2. Enumeration: The serialization and deserialization of the enumeration is just switching between the enumeration name and the enumeration object, and no new enumeration object will be created;
- 3. List & Set & Map: The container type will create a factory through a preset object, and call the new keyword to create an object;
- 4. Java Bean: The creation of Java Bean is divided into many possibilities:
- Case 1: If the object creation factory is customized
InstanceCreator
, it is first created through the custom factory; - Case 2: If there is a default no-argument constructor, it is created through the reflection constructor;
- Case 3: Use the Unsafe API to create objects.
- Case 1: If the object creation factory is customized
ConstructorConstructor.java
public <T> ObjectConstructor<T> get(TypeToken<T> typeToken) {
final Type type = typeToken.getType();
final Class<? super T> rawType = typeToken.getRawType();
// InstanceCreator API
final InstanceCreator<T> typeCreator = (InstanceCreator<T>) instanceCreators.get(type);
if (typeCreator != null) {
return new ObjectConstructor<T>() {
@Override
public T construct() {
return typeCreator.createInstance(type);
}
};
}
final InstanceCreator<T> rawTypeCreator = (InstanceCreator<T>) instanceCreators.get(rawType);
if (rawTypeCreator != null) {
return new ObjectConstructor<T>() {
@Override
public T construct() {
return rawTypeCreator.createInstance(type);
}
};
}
// 无参构造函数
ObjectConstructor<T> defaultConstructor = newDefaultConstructor(rawType);
if (defaultConstructor != null) {
return defaultConstructor;
}
// 容器类型
ObjectConstructor<T> defaultImplementation = newDefaultImplementationConstructor(type, rawType);
if (defaultImplementation != null) {
return defaultImplementation;
}
// Unsafe API
return newUnsafeAllocator(type, rawType);
}
2.6 Gson Hidden Pit
When Class does not provide a default no-argument constructor, Gson will use the Unsafe API to create objects. The Unsafe API mainly provides methods for performing low-level, unsafe operations, and also provides an unconventional allocateInstance
method .
This API does not call the constructor, so the relevant construction initialization operations will be lost;
- 1. The default value of the constructor parameter is lost;
- 2. The default value of the field is lost;
- 3. Kotlin non-null type is invalid;
- 4. The initialization block is not executed;
- 5. By attribute proxy (no proxy object created)
3. How does Gson resolve generic types?
Since Java has generic erasure, it is impossible to directly declare generic information on .class
the grammar . Gson's method is to require programmers to create anonymous inner classes, and Gson can obtain generic information on class declarations through reflection at runtime.
示例代码
// 非法:
Response<User> obj = Gson().fromJson<Response<User>>(jsonStr, Response<User>.class)
// 合法;
TypeToken token = object : TypeToken<Response<User>>() {
}
Response<User> obj = Gson().fromJson<Response<User>>(jsonStr, token.type)
Why use anonymous inner classes to deserialize generic classes?
The principle is that Signature
the attribute will keep the class signature information, and TypeToken
is just a tool class that internally obtains the generic information in the class signature through reflection and returns Type
the type .
TypeToken.java
protected TypeToken() {
this.type = getSuperclassTypeParameter(getClass());
this.rawType = (Class<? super T>) $Gson$Types.getRawType(type);
this.hashCode = type.hashCode();
}
// 返回 Response<User>
static Type getSuperclassTypeParameter(Class<?> subclass) {
Type superclass = subclass.getGenericSuperclass();
if (superclass instanceof Class) {
throw new RuntimeException("Missing type parameter.");
}
ParameterizedType parameterized = (ParameterizedType) superclass;
return $Gson$Types.canonicalize(parameterized.getActualTypeArguments()[0]);
}
public final Type getType() {
return type;
}
Since TypeToken is just a tool class to obtain the Type type, we can also skip it and directly provide the Type by defining ParameterizedType
a subclass of the parameterized type:
ParameterizedTypeAdapter.java
private static class ParameterizedTypeAdapter implements ParameterizedType {
private final Class<?> rawType;
private final Type[] types;
private ParameterizedTypeAdapter(Class<?> rawType, Type... types) {
this.rawType = rawType;
this.types = types;
}
@Override
public Type[] getActualTypeArguments() {
return types;
}
@Override
public Type getRawType() {
return rawType;
}
@Override
public Type getOwnerType() {
return null;
}
}
示例代码
Response<User> obj = new Gson().fromJson<Response<User>>(jsonStr, ParameterizedTypeAdapter(Response.class, User.class))
In Kotlin, it is also possible to use the reified parameter simplification:
Utils.kt
inline fun <reified T> toList(jsonStr: String): List<T> =
Gson().fromJson(content, ParameterizedTypeAdapter(List::class.java, T::class.java))
inline fun <reified T> toObject(jsonStr: String): List<T> =
Gson().fromJson(content, T::class.java))
示例代码
List<User> obj = toList<User>(jsonStr)
4. Summary
Today, we discussed the basic usage of Gson and the source code analysis of the main process.
In Gson's deserialization, when deserializing a type object for the first time, Gson needs to use a lot of reflection calls to resolve a TypeAdapter adapter object. As the complexity of the Model increases, the time-consuming for the first parsing will continue to expand.
A solution to this problem is mentioned in Douyin’s technical blog. We will discuss this problem in the next article, please pay attention.
References
- Java Google Json (Gson) Introduction —— Mithil Shah 著
- Gson — Getting Started with Java-JSON —— Norman Peitek 著
- Javadoc Gson - Official Gson documentation
- Gson source code analysis and its design pattern - by Latin Wu
- Still being tormented by the serialization of data classes? It's time to ditch Gson - by bennyhuo
- Douyin Android Performance Optimization Series: Startup Optimization Practice (Deserialization Optimization) —— ByteDance Technical Team
- JSON —— Wikipedia, the free encyclopedia