Gson源码版本

1
2
3
4
5
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.6</version>
</dependency>

summary

  • 抽象类TypeAdapter,委托模式,处理json字符串和特定类型对象之间的相互转换。抽象方法read和write在具体的TypeAdapter有各自的实现,比较复杂的包括集合类型的CollectionTypeAdapterFactory.Adapter(比如read时,要实例化集合,再循环处理集合内元素)、自定义对象类型的ReflectiveTypeAdapterFactory.Adapter(比如需要循环处理类内field的read和write)。
  • 接口TypeAdapterFactory,抽象工厂模式,创建给定类型的TypeAdapter。基础类型已经预先创建typeAdapter(调用factory.create时,如果是给定的类型,返回预定义的adapter),Collection、自定义类型等包含泛型的,在运行时create(因为会有不同的要素,比如constructor、elementType、boundFields等)。
  • 序列化时,泛型类型通过TypeAdapterRuntimeTypeWrapper进行处理。会判断使用rawType带过来的类型还是运行时真实value的类型进行后续处理。
  • 责任链模式(?待确认)。在对顶层类型getAdapter过程中,会递归对下层类型进行getAdapter,并保存在上层adapter中;在顶层adapter.write过程中,也递归调用到子类型的adapter.write。ps在基本类型adapter中,才调用JsonReader/Writer读写。

设计模式

工厂模式

TypeAdapterFactory.create提供给定TypeToken的TypeAdapter.

1
2
3
4
5
6
7
8
public interface TypeAdapterFactory {

/**
* Returns a type adapter for {@code type}, or null if this factory doesn't
* support {@code type}.
*/
<T> TypeAdapter<T> create(Gson gson, TypeToken<T> type);
}

factory和adapter

Gson内置factory

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
   List<TypeAdapterFactory> factories = new ArrayList<TypeAdapterFactory>();

// Gson的类型
// built-in type adapters that cannot be overridden
factories.add(TypeAdapters.JSON_ELEMENT_FACTORY);
factories.add(ObjectTypeAdapter.FACTORY);

// the excluder must precede all adapters that handle user-defined types
factories.add(excluder);

// 用户定义的TypeAdapters
// user's type adapters
factories.addAll(typeAdapterFactories);

// 基础类型
// type adapters for basic platform types
factories.add(TypeAdapters.STRING_FACTORY);
factories.add(TypeAdapters.INTEGER_FACTORY);
factories.add(TypeAdapters.BOOLEAN_FACTORY);
factories.add(TypeAdapters.BYTE_FACTORY);
factories.add(TypeAdapters.SHORT_FACTORY);
factories.add(TypeAdapters.newFactory(long.class, Long.class,
longAdapter(longSerializationPolicy)));
factories.add(TypeAdapters.newFactory(double.class, Double.class,
doubleAdapter(serializeSpecialFloatingPointValues)));
factories.add(TypeAdapters.newFactory(float.class, Float.class,
floatAdapter(serializeSpecialFloatingPointValues)));
factories.add(TypeAdapters.NUMBER_FACTORY);
factories.add(TypeAdapters.CHARACTER_FACTORY);
factories.add(TypeAdapters.STRING_BUILDER_FACTORY);
factories.add(TypeAdapters.STRING_BUFFER_FACTORY);
factories.add(TypeAdapters.newFactory(BigDecimal.class, TypeAdapters.BIG_DECIMAL));
factories.add(TypeAdapters.newFactory(BigInteger.class, TypeAdapters.BIG_INTEGER));
factories.add(TypeAdapters.URL_FACTORY);
factories.add(TypeAdapters.URI_FACTORY);
factories.add(TypeAdapters.UUID_FACTORY);
factories.add(TypeAdapters.LOCALE_FACTORY);
factories.add(TypeAdapters.INET_ADDRESS_FACTORY);
factories.add(TypeAdapters.BIT_SET_FACTORY);
factories.add(DateTypeAdapter.FACTORY);
factories.add(TypeAdapters.CALENDAR_FACTORY);
factories.add(TimeTypeAdapter.FACTORY);
factories.add(SqlDateTypeAdapter.FACTORY);
factories.add(TypeAdapters.TIMESTAMP_FACTORY);
factories.add(ArrayTypeAdapter.FACTORY);
factories.add(TypeAdapters.CLASS_FACTORY);

// 组合类型和自定义类型
// type adapters for composite and user-defined types
factories.add(new CollectionTypeAdapterFactory(constructorConstructor));
factories.add(new MapTypeAdapterFactory(constructorConstructor, complexMapKeySerialization));
factories.add(new JsonAdapterAnnotationTypeAdapterFactory(constructorConstructor));
factories.add(TypeAdapters.ENUM_FACTORY);
factories.add(new ReflectiveTypeAdapterFactory(
constructorConstructor, fieldNamingPolicy, excluder));

newFactory

typeToken.getRawType()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
  public static <TT> TypeAdapterFactory newFactory(
final Class<TT> type, final TypeAdapter<TT> typeAdapter) {
return new TypeAdapterFactory() {
@SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal
@Override public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
return typeToken.getRawType() == type ? (TypeAdapter<T>) typeAdapter : null;
}
@Override public String toString() {
return "Factory[type=" + type.getName() + ",adapter=" + typeAdapter + "]";
}
};
}

// 装箱+非装箱
public static <TT> TypeAdapterFactory newFactory(
final Class<TT> unboxed, final Class<TT> boxed, final TypeAdapter<? super TT> typeAdapter) {
return new TypeAdapterFactory() {
@SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal
@Override public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
Class<? super T> rawType = typeToken.getRawType();
return (rawType == unboxed || rawType == boxed) ? (TypeAdapter<T>) typeAdapter : null;
}
@Override public String toString() {
return "Factory[type=" + boxed.getName()
+ "+" + unboxed.getName() + ",adapter=" + typeAdapter + "]";
}
};
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
  public static final TypeAdapterFactory TIMESTAMP_FACTORY = new TypeAdapterFactory() {
@SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal
@Override public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
if (typeToken.getRawType() != Timestamp.class) {
return null;
}
// gson.getAdapter(Date.class)的逻辑?
final TypeAdapter<Date> dateTypeAdapter = gson.getAdapter(Date.class);
return (TypeAdapter<T>) new TypeAdapter<Timestamp>() {
@Override public Timestamp read(JsonReader in) throws IOException {
Date date = dateTypeAdapter.read(in);
return date != null ? new Timestamp(date.getTime()) : null;
}

@Override public void write(JsonWriter out, Timestamp value) throws IOException {
dateTypeAdapter.write(out, value);
}
};
}
};

CALENDAR和LOCALE的factory、adapter

可以学习

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
public static final TypeAdapter<Calendar> CALENDAR = new TypeAdapter<Calendar>() {
private static final String YEAR = "year";
private static final String MONTH = "month";
private static final String DAY_OF_MONTH = "dayOfMonth";
private static final String HOUR_OF_DAY = "hourOfDay";
private static final String MINUTE = "minute";
private static final String SECOND = "second";

@Override
public Calendar read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
in.beginObject();
int year = 0;
int month = 0;
int dayOfMonth = 0;
int hourOfDay = 0;
int minute = 0;
int second = 0;
while (in.peek() != JsonToken.END_OBJECT) {
String name = in.nextName();
int value = in.nextInt();
if (YEAR.equals(name)) {
year = value;
} else if (MONTH.equals(name)) {
month = value;
} else if (DAY_OF_MONTH.equals(name)) {
dayOfMonth = value;
} else if (HOUR_OF_DAY.equals(name)) {
hourOfDay = value;
} else if (MINUTE.equals(name)) {
minute = value;
} else if (SECOND.equals(name)) {
second = value;
}
}
in.endObject();
return new GregorianCalendar(year, month, dayOfMonth, hourOfDay, minute, second);
}

@Override
public void write(JsonWriter out, Calendar value) throws IOException {
if (value == null) {
out.nullValue();
return;
}
out.beginObject();
out.name(YEAR);
out.value(value.get(Calendar.YEAR));
out.name(MONTH);
out.value(value.get(Calendar.MONTH));
out.name(DAY_OF_MONTH);
out.value(value.get(Calendar.DAY_OF_MONTH));
out.name(HOUR_OF_DAY);
out.value(value.get(Calendar.HOUR_OF_DAY));
out.name(MINUTE);
out.value(value.get(Calendar.MINUTE));
out.name(SECOND);
out.value(value.get(Calendar.SECOND));
out.endObject();
}
};

public static final TypeAdapterFactory CALENDAR_FACTORY =
newFactoryForMultipleTypes(Calendar.class, GregorianCalendar.class, CALENDAR);

public static final TypeAdapter<Locale> LOCALE = new TypeAdapter<Locale>() {
@Override
public Locale read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
String locale = in.nextString();
StringTokenizer tokenizer = new StringTokenizer(locale, "_");
String language = null;
String country = null;
String variant = null;
if (tokenizer.hasMoreElements()) {
language = tokenizer.nextToken();
}
if (tokenizer.hasMoreElements()) {
country = tokenizer.nextToken();
}
if (tokenizer.hasMoreElements()) {
variant = tokenizer.nextToken();
}
if (country == null && variant == null) {
return new Locale(language);
} else if (variant == null) {
return new Locale(language, country);
} else {
return new Locale(language, country, variant);
}
}
@Override
public void write(JsonWriter out, Locale value) throws IOException {
out.value(value == null ? null : value.toString());
}
};

public static final TypeAdapterFactory LOCALE_FACTORY = newFactory(Locale.class, LOCALE);

Enum的泛型实现

可以看下jackson的实现,以后枚举字段可以直接用枚举值,注解使用code来序列化(不过还要注意vo和po的转换,DAO层和数据库是怎么支持枚举的?)

class1.isAssignableFrom(class2) 表示 class1是class2的超类或本身

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
private static final class EnumTypeAdapter<T extends Enum<T>> extends TypeAdapter<T> {
// 序列化名称到枚举的映射
private final Map<String, T> nameToConstant = new HashMap<String, T>();
// 枚举到名称的映射,如果有SerializedName的注解,用注解的名称,否则用枚举自身的名称
private final Map<T, String> constantToName = new HashMap<T, String>();

public EnumTypeAdapter(Class<T> classOfT) {
try {
// classOfT.getEnumConstants() 获取枚举
for (T constant : classOfT.getEnumConstants()) {
String name = constant.name();
SerializedName annotation = classOfT.getField(name).getAnnotation(SerializedName.class);
if (annotation != null) {
name = annotation.value();
for (String alternate : annotation.alternate()) {
nameToConstant.put(alternate, constant);
}
}
nameToConstant.put(name, constant);
constantToName.put(constant, name);
}
} catch (NoSuchFieldException e) {
throw new AssertionError(e);
}
}
@Override public T read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
return nameToConstant.get(in.nextString());
}

@Override public void write(JsonWriter out, T value) throws IOException {
out.value(value == null ? null : constantToName.get(value));
}
}

public static final TypeAdapterFactory ENUM_FACTORY = new TypeAdapterFactory() {
@SuppressWarnings({"rawtypes", "unchecked"})
@Override public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
Class<? super T> rawType = typeToken.getRawType();
// 判断Enum是rawType的超类
if (!Enum.class.isAssignableFrom(rawType) || rawType == Enum.class) {
return null;
}
if (!rawType.isEnum()) {
rawType = rawType.getSuperclass(); // handle anonymous subclasses
}
return (TypeAdapter<T>) new EnumTypeAdapter(rawType);
}
};

InetAdress和JsonElement是用超类Adapter工作的

image-20200319150955172

基本类型的factory和adapter

Long/Float/Double的adapter根据序列化自定义而不同

image-20200319151507859

复杂类型的factory和adapter

image-20200319151622774

CollectionTypeAdapterFactory 集合类型

ReflectiveTypeAdapterFactory 自定义对象

TypeAdapterRuntimeTypeWrapper

是对TypeAdapter的封装,用于write运行时判断更准确的类型。

在array/collection/map/自定义类型等adapter中使用。

比如Object a = new String(“aaa”),实际上应使用StringTypeAdapter来write。

read时,以什么样的类型赋值给a?

image-20200322155848761

TypeToken

匿名内部类有两种语法格式

  • new 接口(){}
  • new 父类构造器(参数列表){}
    TypeToken为第二种
    new TypeToken<List<TwoGeneric<Integer,User>>>(){};得到的是TypeToken<List<TwoGeneric<Integer,User>>>的匿名子类。

$Gson$Types

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public static Class<?> getRawType(Type type) {
if (type instanceof Class<?>) {
// type is a normal class.
return (Class<?>) type;

} else if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) type;

// I'm not exactly sure why getRawType() returns Type instead of Class.
// Neal isn't either but suspects some pathological case related
// to nested classes exists.
Type rawType = parameterizedType.getRawType();
checkArgument(rawType instanceof Class);
return (Class<?>) rawType;

} else if (type instanceof GenericArrayType) {
Type componentType = ((GenericArrayType)type).getGenericComponentType();
return Array.newInstance(getRawType(componentType), 0).getClass();

} else if (type instanceof TypeVariable) {
// we could use the variable's bounds, but that won't work if there are multiple.
// having a raw type that's more general than necessary is okay
return Object.class;

} else if (type instanceof WildcardType) {
return getRawType(((WildcardType) type).getUpperBounds()[0]);

} else {
String className = type == null ? "null" : type.getClass().getName();
throw new IllegalArgumentException("Expected a Class, ParameterizedType, or "
+ "GenericArrayType, but <" + type + "> is of type " + className);
}
}

序列化与反序列化结果类型对比

  1. wildcard类型,根据上界反序列化。upperBoundList的上界是TestInnerObject,?是TestInnerSonObject,反序列化丢失了innerSonId的值。lowerBoundList的上界是Object,反序列化为map
  2. 声明的类型为Object,write正常,read为map

image-20200322164050596

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
@Test
public void testGson() {
Gson gson = new Gson();

TestInnerObject testInnerObject = new TestInnerObject();
testInnerObject.setInnerId("inner");

TestInnerParentObject testInnerParentObject = new TestInnerParentObject();
testInnerParentObject.setInnerParentId("parent");

TestInnerSonObject testInnerSonObject = new TestInnerSonObject();
testInnerSonObject.setInnerSonId("son");

TestObject testObject = new TestObject();
testObject.setString("mock");
testObject.setLongList(Lists.newArrayList(1L, 2L));
Map<String, TestInnerObject> map = Maps.newHashMap();
map.put("mockKey", testInnerObject);
testObject.setMap(map);
testObject.setUpperBoundList(Lists.newArrayList(testInnerSonObject));
testObject.setLowerBoundList(Lists.newArrayList(testInnerParentObject));
testObject.setObject(testInnerSonObject);
testObject.setLists(new List[]{Lists.newArrayList(testInnerObject)});

String json = gson.toJson(testObject);
log.info("json = {}", json);

testObject = gson.fromJson(json, TestObject.class);
log.info("testObject = {}", testObject);
}

@Data
public class TestObject {
private String string;
private List<Long> longList;
private List<TestInnerObject> testInnerObjectList;
private Map<String, TestInnerObject> map;
private List<? extends TestInnerObject> upperBoundList;
private List<? super TestInnerObject> lowerBoundList;
private TestObject[] testObjectArray;
private List[] lists;
private Object object;
}

@Data
public class TestInnerObject extends TestInnerParentObject {
private String innerId;
}

@Data
public class TestInnerParentObject {
private String innerParentId;
}

@Data
public class TestInnerSonObject extends TestInnerObject {
private String innerSonId;
}

todo

  • map 复杂key的序列化
  • map peek == JsonToken.BEGIN_ARRAY
  • reflectiveTypeAdapter 多个泛型 [done. read时根据name和TypeToken,write时根据TypeAdapterRuntimeTypeWrapper]
  • toJson时候,type里带实例的runtime type? [done. TypeAdapterRuntimeTypeWrapper处理]
  • JsonAdapterAnnotationTypeAdapterFactory [almost done. 获取filed上注解的TypeAdapter进行后续处理]
  • $Gson$Types.resolve [done]
  • JsonWriter和JsonReader的读写 [almost done. 写比较简单,不同类型输出;读在fillBuffer时先读到缓存中,不同类型在缓存中操作。]
  • read之后怎么赋值?
  • 装箱和非装箱,都是用的装箱adapter,返回装箱类型。—-那装箱类型赋值给非装箱类型吗?用set还是set方法?
  • TypeToken的rawType是怎么取到的?
  • gson.getAdapter(Date.class)的逻辑?