介绍
Gson 是 Google 提供的用来在 Java 对象和 JSON 数据之间进行映射的 Java 类库。可以将一个 JSON 字符串转成一个 Java 对象,或者反过来。
基本概念
-
Serialization:序列化,使Java对象到Json字符串的过程。
-
Deserialization:反序列化,字符串转换成Java对象。
-
JSON数据中的
JsonElement
有下面这四种类型:JsonPrimitive -- JsonElement的子类,该类对Java的基本类型及其对应的包装类进行了封装,并通过setValue方法为value赋值。
JsonObject -- json对象类,包含了键值对,键是字符串类型,值是一个JsonElement。用 LinkedTreeMap<String, JsonElement> members来保存。
JsonArray -- Json的数组包含的其实也是一个个Json串,用
List<JsonElement>
来添加json数组中的每个元素JsonNull -- 不可变类
能解决的问题
-
提供一种像toString()和构造方法的很简单的机制,来实现Java 对象和Json之间的互相转换。
-
允许已经存在的无法改变的对象,转换成Json,或者Json转换成已存在的对象。
-
允许自定义对象的表现形式
-
支持任意的复杂对象
-
能够生成可压缩和可读的Json的字符串输出。
Gson处理对象的几个要点
1 推荐把成员变量都声明称private的
2 没有必要用注解(@Expose 注解)指明某个字段是否会被序列化或者反序列化,所有包含在当前类(包括父类)中的字段都应该默认被序列化或者反序列化
3 如果某个字段被 transient 这个Java关键词修饰,就不会被序列化或者反序列化
4 下面的实现方式能够正确的处理null
1)当序列化的时候,如果对象的某个字段为null,是不会输出到Json字符串中的。
2)当反序列化的时候,某个字段在Json字符串中找不到对应的值,就会被赋值为null
5 如果一个字段是 synthetic的,他会被忽视,也即是不应该被序列化或者反序列化
6 内部类(或者anonymous class(匿名类),或者local class(局部类,可以理解为在方法内部声明的类))的某个字段和外部类的某个字段一样的话,就会被忽视,不会被序列化或者反序列化
常见的注解
@SerializedName注解 ---指定该字段在json中对应的字段名称
@SerializedName("companyId")
private String id;
@Expose注解 ---指定该字段是否能够序列化或者反序列化,默认的是都支持(true)
@Expose(serialize = false)
private String name;
@Since --- 自从
@Since(1.2) //从版本1.2之后才生效
private int shirtNumber;
@Until --- 一直到
@Until(0.9) //在0.9版本之前都是生效的
private String companyName;
Gson 序列化
Java类
public class Book {
private String[] authors;
private String isbn10;
private String isbn13;
private String title;
//为了代码简洁,这里移除getter和setter方法等
}
希望的json数据
{
"title": "Java Puzzlers: Traps, Pitfalls, and Corner Cases",
"isbn-10": "032133678X",
"isbn-13": "978-0321336781",
"authors": [
"Joshua Bloch",
"Neal Gafter"
]
}
JSON数据中出现了isbn-10
和isbn-13
, 我们怎么把字段数据isbn10
和isbn13
转化为JSON数据需要的isbn-10
和isbn-13
,Gson当然为我们提供了对应的解决方案。
1.@SerializedName
注解
public class Book {
private String[] authors;
@SerializedName("isbn-10")
private String isbn10;
@SerializedName("isbn-13")
private String isbn13;
private String title;
//为了代码简洁,这里移除getter和setter方法等
}
2.利用JsonSerializer
类
public class BookSerialiser implements JsonSerializer {
@Override
public JsonElement serialize(final Book book, final Type typeOfSrc, final JsonSerializationContext context) {
final JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("title", book.getTitle());
jsonObject.addProperty("isbn-10", book.getIsbn10());
jsonObject.addProperty("isbn-13", book.getIsbn13());
final JsonArray jsonAuthorsArray = new JsonArray();
for (final String author : book.getAuthors()) {
final JsonPrimitive jsonAuthor = new JsonPrimitive(author);
jsonAuthorsArray.add(jsonAuthor);
}
jsonObject.add("authors", jsonAuthorsArray);
return jsonObject;
}
}
- JsonSerializer是一个接口,我们需要提供自己的实现,来满足自己的序列化要求。
public interface JsonSerializer<T> {
public JsonElement serialize(T src, Type typeOfSrc, JsonSerializationContext context);
}
- 我们需要创建的是一个JsonElement对象,这里对应Book是一个对象,所以创建一个JsonObject类型。
- 然后我们将相应字段里面的数据填充到jsonObject里面。
- 所以最后返回的还是一个JsonElement 类型,这里对应的是jsonObject。完成了javaBean->JSON数据的转化。
gsonBuilder.registerTypeAdapter(Book.class, new BookSerialiser())
方法进行JsonSerializer的配置。通过调用gsonBuilder.setPrettyPrinting();
方法还告诉了 Gson 对生成的 JSON 对象进行格式化。
Gson gson = new GsonBuilder()
.registerTypeAdapter(Book.class, new BookSerialiser())
.enableComplexMapKeySerialization()
.serializeNulls()
.setDateFormat(DateFormat.LONG)
.setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
.setPrettyPrinting()
.setVersion(1.0)
.create();
Gson 反序列化
json串
{
"title": "Java Puzzlers: Traps, Pitfalls, and Corner Cases",
"isbn-10": "032133678X",
"isbn-13": "978-0321336781",
"authors": [
"Joshua Bloch",
"Neal Gafter"
]
}
目标: Book对象
方案1: 利用@SerializedName
注解
public class Book {
private String[] authors;
@SerializedName("isbn-10")
private String isbn10;
@SerializedName(value = "isbn-13", alternate = {"isbn13","isbn.13"})
private String isbn13;
private String title;
//为了代码简洁,这里移除getter和setter方法等
}
我们在@SerializedName
注解使用了一个value
, alternate
字段,value
也就是默认的字段,对序列化和反序列化都有效,alternate
只有反序列化才有效果。也就是说一般服务器返回给我们JSON数据的时候可能同样的一个图片,表示"image","img","icon"等,我们利用@SerializedName
中的alternate
字段就能解决这个问题,全部转化为我们实体类中的图片字段。
方案二:使用JsonDeserializer
public class BookDeserializer implements JsonDeserializer<Book> {
@Override
public Book deserialize(final JsonElement json, final Type typeOfT, final JsonDeserializationContext context)
throws JsonParseException {
final JsonObject jsonObject = json.getAsJsonObject();
final JsonElement jsonTitle = jsonObject.get("title");
final String title = jsonTitle.getAsString();
final String isbn10 = jsonObject.get("isbn-10").getAsString();
final String isbn13 = jsonObject.get("isbn-13").getAsString();
final JsonArray jsonAuthorsArray = jsonObject.get("authors").getAsJsonArray();
final String[] authors = new String[jsonAuthorsArray.size()];
for (int i = 0; i < authors.length; i++) {
final JsonElement jsonAuthor = jsonAuthorsArray.get(i);
authors[i] = jsonAuthor.getAsString();
}
final Book book = new Book();
book.setTitle(title);
book.setIsbn10(isbn10);
book.setIsbn13(isbn13);
book.setAuthors(authors);
return book;
}
}
- 通过
final JsonObject jsonObject = json.getAsJsonObject();
将我们的JsonElement转化为JsonObject - 通过
jsonObject.get("xxx").getAsString()
的形式获取相应String的值 - 通过
jsonObject.get("xx").getAsJsonArray();
获取相应的json数组,并遍历出其中的相应字段值 - 通过setter方法,将获取到的值设置给Book类。
- 最终返回的是 Book的对象实例。完成了JSON->javaBean的转化
gsonBuilder.registerTypeAdapter(Book.class, new BookSerialiser())
方法进行JsonSerializer的配置。- 从本地流中读取Json数据(可以使用
InputStreamReader
完成)
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Book.class, new BookDeserializer());
Gson gson = gsonBuilder.create();
// The JSON data
try(Reader reader = new InputStreamReader(Main.class.getResourceAsStream("/part1/sample.json"), "UTF-8")){
// Parse JSON to Java
Book book = gson.fromJson(reader, Book.class);
System.out.println(book);
}
TypeAdapter介绍
我们在把Java对象转化为JSON字符串的时候都会用到这个中间件
JsonElement
,而TypeAdapter
的使用正是去掉了这个中间层,直接用流来解析数据,极大程度上提高了解析效率。
TypeAdapter
作为一个抽象类提供两个抽象方法。分别是write()
和read()
方法,也对应着序列化和反序列化。
TypeAdapter的小demo
->> Book实体类
public class Book {
private String[] authors;
private String isbn;
private String title;
//为了代码简洁,这里移除getter和setter方法等
}
->> BookTypeAdapter 具体序列化和反序列化的TypeAdapter
类
public class BookTypeAdapter extends TypeAdapter {
@Override
public Book read(final JsonReader in) throws IOException {
final Book book = new Book();
in.beginObject();
while (in.hasNext()) {
switch (in.nextName()) {
case "isbn":
book.setIsbn(in.nextString());
break;
case "title":
book.setTitle(in.nextString());
break;
case "authors":
book.setAuthors(in.nextString().split(";"));
break;
}
}
in.endObject();
return book;
}
@Override
public void write(final JsonWriter out, final Book book) throws IOException {
out.beginObject();
out.name("isbn").value(book.getIsbn());
out.name("title").value(book.getTitle());
out.name("authors").value(StringUtils.join(book.getAuthors(), ";"));
out.endObject();
}
}
->>注册
final GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Book.class, new BookTypeAdapter());
final Gson gson = gsonBuilder.create();
JsonReader的作用
读取json字符串并转化为一个token流,而JsonParser就是根据这个token流进行json语法分析并转为java对象。
TypeToken
Java的泛型在运行时会有类型擦除,Gson解析将得不到预期的类型,TypeToken就是解决这个问题的。解决方案就是:匿名类+反射。
TypeToken(Type type) {
this.type = $Gson$Types.canonicalize($Gson$Preconditions.checkNotNull(type));
this.rawType = (Class<? super T>) $Gson$Types.getRawType(this.type);
this.hashCode = this.type.hashCode();
}
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]);
}
原理就是用一个继承TypeToken的匿名类,从而获取该匿名类的泛型超类,然后将该泛型超类强制转换为ParameterizedType。ParameterizedType包含了获取其实际类型参数的方法getActualTypeArguments()及获取其原始类型的方法getRawType()。
public class TypeTokenTest {
//待解析的json字符串: {"data":"data from server"}
public class Response<T>{
public T data;//简化数据, 省略了其他字段
@Override
public String toString() {
return "Response{" +
"data=" + data +
'}';
}
}
private Response<String> data;
public static void main(String[] args) {
String json = "{\"data\":\"data from server\"}";
//fromJson(String json, Class<T> classOfT)的第二个参数classOfT期望获取Response<String>这种类型
//Class responseClass = Response<String>.class; /但是这么写不能通过编译,因为Response<String>不是一个Class类型
Class responseClass = Response.class; //只能这样获取类型, 但无法知道Response里面数据的类型
Response<String> result = (Response<String>) new Gson().fromJson(json, responseClass);
System.out.println("result=" + result);
//Gson的解决方案
Type type = new TypeToken<Response<String>>(){}.getType();
System.out.println("type=" + type);//TypeTokenTest$Response<java.lang.String>
result = new Gson().fromJson(json, type);
System.out.println("result=" + result);
}
}
new TypeToken<Response>(){} 实例化的过程:
1. class TypeToken$0 extends TypeToken<Response<String>>{ }
2. TypeToken typeToken = new TypeToken$0();
TypeToken0类型的,父类型是TypeToken<Response>,而不是TypeToken,Type superclass = subclass.getGenericSuperclass(),得到的superclass 是TypeToken<Response>,而不是TypeToken。继续调用parameterized.getActualTypeArguments()[0] 得到的是Response
这也是为什么TypeToken的构造方法是protected的,想要调用该类的public方法不能够直接new一个TypeToken对象,可以新建一个匿名类(new TypeToken(){})或者新建一个类继承TypeToken来得到这个类的实例,然后调用该类的public方法
write方法
public void write(final JsonWriter out, final Book book) throws IOException {
out.beginObject();
out.name("isbn").value(book.getIsbn());
out.name("title").value(book.getTitle());
out.name("authors").value(StringUtils.join(book.getAuthors(), ";"));
out.endObject();
}
传入JsonWriter
,和需要被序列化的Book
对象的实例,采用和PrintStream
类似的方式 写入到JsonWriter
中。
out.beginObject()
产生{
,如果我们希望产生的是一个数组对象,对应的使用beginArray()
public JsonWriter beginObject() throws IOException {
writeDeferredName();
return open(EMPTY_OBJECT, "{");
}
out.name("isbn").value(book.getIsbn()); out.name("title").value(book.getTitle());
分别获取book中的isbn和title字段并且设置给Json对象中的isbn和title。- out.name("authors").value(StringUtils.join(book.getAuthors(), ";"));
out.endObject()
则对应着}
最后的json
{
"isbn": "978-0321336781",
"title": "Java Puzzlers: Traps, Pitfalls, and Corner Cases",
"authors": "Joshua Bloch;Neal Gafter"
}
read方法
传入一个JsonReader
对象实例并返回反序列化的对象。
public Book read(final JsonReader in) throws IOException {
final Book book = new Book();
in.beginObject();
while (in.hasNext()) {
switch (in.nextName()) {
case "isbn":
book.setIsbn(in.nextString());
break;
case "title":
book.setTitle(in.nextString());
break;
case "authors":
book.setAuthors(in.nextString().split(";"));
break;
}
}
in.endObject();
return book;
}
- 同样是通过
in.beginObject();
和in.endObject();
对应解析{
,}
- 通过while循环遍历每一个JsonElement来给实体类设置对应的值
TypeAdapter的工作方式
- 通过GsonBuilder注册TypeAdapter,并把TypeAdapter封装成TypeAdpterFactory对象
- 将封装成的TypeAdapterFactory通过GsonBuilder的create方法传入Gson对象中
- 调用gson.fromJson方法,调用getAdapter方法返回自定义的Adapter,并调用其reader方法将json转为java对象
TypeAdapterFactory
在Gson中有大量的TypeAdapterFactory,比如基本类型都对应一个TypeAdapter,每个TypeAdapter都对应一个TypeAdapterFactory
public static final TypeAdapter<Number> INTEGER = new TypeAdapter<Number>() {
@Override
public Number read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
try {
return in.nextInt();
} catch (NumberFormatException e) {
throw new JsonSyntaxException(e);
}
}
@Override
public void write(JsonWriter out, Number value) throws IOException {
out.value(value);
}
};
public static final TypeAdapterFactory INTEGER_FACTORY
= newFactory(int.class, Integer.class, INTEGER);
public static final TypeAdapter<AtomicInteger> ATOMIC_INTEGER = new TypeAdapter<AtomicInteger>() {
@Override public AtomicInteger read(JsonReader in) throws IOException {
try {
return new AtomicInteger(in.nextInt());
} catch (NumberFormatException e) {
throw new JsonSyntaxException(e);
}
}
自定义TypeAdapter实际上就是先转换成TypeAdapterFactory然后在Gson的getAdapter方法中遍历TyperAdapterFactory,并调用create方法得到TypeAdapter
public GsonBuilder registerTypeAdapterFactory(TypeAdapterFactory factory) {
factories.add(factory);
return this;
}
在new Gson()这个Gson默认构造器的时候,其实调用了另外一个带参数的构造器进行初始化
public Gson() {
this(Excluder.DEFAULT, FieldNamingPolicy.IDENTITY,
Collections.<Type, InstanceCreator<?>>emptyMap(), DEFAULT_SERIALIZE_NULLS,
DEFAULT_COMPLEX_MAP_KEYS, DEFAULT_JSON_NON_EXECUTABLE, DEFAULT_ESCAPE_HTML,
DEFAULT_PRETTY_PRINT, DEFAULT_LENIENT, DEFAULT_SPECIALIZE_FLOAT_VALUES,
LongSerializationPolicy.DEFAULT, null, DateFormat.DEFAULT, DateFormat.DEFAULT,
Collections.<TypeAdapterFactory>emptyList(), Collections.<TypeAdapterFactory>emptyList(),
Collections.<TypeAdapterFactory>emptyList());
}
带有参数的构造器的的其中一个作用就是为Gson对象的 factories 添加大量的Gson自带的TypeAdapterFactory:
// users' type adapters
factories.addAll(factoriesToBeAdded);
// 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);
TypeAdapter<Number> longAdapter = longAdapter(longSerializationPolicy);
factories.add(TypeAdapters.newFactory(long.class, Long.class, longAdapter));
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.ATOMIC_INTEGER_FACTORY);
factories.add(TypeAdapters.ATOMIC_BOOLEAN_FACTORY);
factories.add(TypeAdapters.newFactory(AtomicLong.class, atomicLongAdapter(longAdapter)));
factories.add(TypeAdapters.newFactory(AtomicLongArray.class, atomicLongArrayAdapter(longAdapter)));
factories.add(TypeAdapters.ATOMIC_INTEGER_ARRAY_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.CURRENCY_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));
this.jsonAdapterFactory = new JsonAdapterAnnotationTypeAdapterFactory(constructorConstructor);
factories.add(jsonAdapterFactory);
factories.add(TypeAdapters.ENUM_FACTORY);
factories.add(new ReflectiveTypeAdapterFactory(
constructorConstructor, fieldNamingStrategy, excluder, jsonAdapterFactory));
this.factories = Collections.unmodifiableList(factories);
添加TypeAdapterFactory的顺序是先添加 用户自定义的TypeAdapterFactory,然后添加 Gson自带的TypeAdapterFactory,最后添加ReflectiveTypeAdapterFactory。Gson解析的时候也是根据这个顺序来获取TypeAdapterFactory的
public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {
...
try {
FutureTypeAdapter<T> call = new FutureTypeAdapter<T>();
threadCalls.put(type, call);
for (TypeAdapterFactory factory : factories) {
TypeAdapter<T> candidate = factory.create(this, type);
if (candidate != null) {
call.setDelegate(candidate);
typeTokenCache.put(type, candidate);
return candidate;
}
}
...
}
getAdapter方法会遍历factories,根据type去获取TypeAdapterFactory,for循环中只要TypeAdapterFactory.create返回的TypeAdapter!=null 则返回创建的TypeAdapter,用该TypeAdapter解析json,因为用户自定义的TypeAdapterFactory和Gson自带的TypeAdapterFactory位置在factories的前面,优先于ReflectiveTypeAdapterFactory遍历到,所以就避免了用Gson的反射机制来解析json了。
ReflectiveTypeAdapterFactory
调用ReflectiveTypeAdapterFactory的create方法,返回一个ReflectiveTypeAdapterFactory.Adapter对象
@Override public <T> TypeAdapter<T> create(Gson gson, final TypeToken<T> type) {
Class<? super T> raw = type.getRawType();
if (!Object.class.isAssignableFrom(raw)) {
return null; // it's a primitive!
}
ObjectConstructor<T> constructor = constructorConstructor.get(type);
return new Adapter<T>(constructor, getBoundFields(gson, type, raw));
}
ObjectConstructor
ObjectConstructor构造器对象用于Adapter在解析json时进行构造对象。而这个ObjectConstructor是来自于一个constructorConstructor的对象,ConstructorConstructor即构建构造器的意思,即用于创建ObjectConstructor构造器对象。
constructorConstructor在构造时,传入了一个instanceCreators对象,这个对象是一个享元对象。默认的情况下,这个对象为空,如果你有自己构造一个对象的需求,可以注入这个对象。那么,Gson会优先选择你注入的这个对象构造器来改造最终对象,我们来看下ConstructorConstructor的ObjectConstructor get(TypeToken typeToken)方法:
public <T> ObjectConstructor<T> get(TypeToken<T> typeToken) {
final Type type = typeToken.getType();
final Class<? super T> rawType = typeToken.getRawType();
//先通过type去获取InstanceCreator,如果获取到InstanceCreator,则通过它来创建构造器对象
// first try an instance creator
@SuppressWarnings("unchecked") // types must agree
final InstanceCreator<T> typeCreator = (InstanceCreator<T>) instanceCreators.get(type);
if (typeCreator != null) {
return new ObjectConstructor<T>() {
@Override public T construct() {
return typeCreator.createInstance(type);
}
};
}
//再通过rawType去获取InstanceCreator,如果获取到InstanceCreator,则通过它来创建构造器对象
// Next try raw type match for instance creators
@SuppressWarnings("unchecked") // types must agree
final InstanceCreator<T> rawTypeCreator =
(InstanceCreator<T>) instanceCreators.get(rawType);
if (rawTypeCreator != null) {
return new ObjectConstructor<T>() {
@Override public T construct() {
return rawTypeCreator.createInstance(type);
}
};
}
//如果是普通类,将使用newDefaultConstructor方法创建一个默认的构造器对象
ObjectConstructor<T> defaultConstructor = newDefaultConstructor(rawType);
if (defaultConstructor != null) {
return defaultConstructor;
}
//如果是接口类,将通过newDefaultImplementationConstructor方法创建一个默认的构造器对象
ObjectConstructor<T> defaultImplementation = newDefaultImplementationConstructor(type, rawType);
if (defaultImplementation != null) {
return defaultImplementation;
}
//如果自定义的java类中没有默认构造器,那么最终会调用newUnsafeAllocator方法来为你创建对应的Java对象
// finally try unsafe
return newUnsafeAllocator(type, rawType);
}
private <T> ObjectConstructor<T> newDefaultConstructor(Class<? super T> rawType) {
try {
//此方法返回具有指定参数列表的构造函数对象,在这里没有传参数,即获取默认的构造器
final Constructor<? super T> constructor = rawType.getDeclaredConstructor();
if (!constructor.isAccessible()) {
accessor.makeAccessible(constructor);
}
return new ObjectConstructor<T>() {
@SuppressWarnings("unchecked") // T is the same raw type as is requested
@Override public T construct() {
try {
Object[] args = null;
return (T) constructor.newInstance(args); //创建Java对象,并返回
} catch (InstantiationException e) {
// TODO: JsonParseException ?
throw new RuntimeException("Failed to invoke " + constructor + " with no args", e);
} catch (InvocationTargetException e) {
// TODO: don't wrap if cause is unchecked!
// TODO: JsonParseException ?
throw new RuntimeException("Failed to invoke " + constructor + " with no args",
e.getTargetException());
} catch (IllegalAccessException e) {
throw new AssertionError(e);
}
}
};
} catch (NoSuchMethodException e) {
return null;
}
}
getBoundFields方法
private Map<String, BoundField> getBoundFields(Gson context, TypeToken<?> type, Class<?> raw) {
Map<String, BoundField> result = new LinkedHashMap<String, BoundField>();
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;
}
accessor.makeAccessible(field);
Type fieldType = $Gson$Types.resolve(type.getType(), raw, field.getGenericType());
List<String> fieldNames = getFieldNames(field);
BoundField previous = null;
for (int i = 0, size = fieldNames.size(); i < size; ++i) {
String name = fieldNames.get(i);
if (i != 0) serialize = false; // only serialize the default name
BoundField boundField = createBoundField(context, field, name,
TypeToken.get(fieldType), serialize, deserialize);
BoundField replaced = result.put(name, boundField);
if (previous == null) previous = replaced;
}
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;
}
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());
// special casing primitives here saves ~5% on Android...
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) {
@SuppressWarnings({"unchecked", "rawtypes"}) // the type adapter and field type always agree
@Override
void write(JsonWriter writer, Object value)
throws IOException, IllegalAccessException {
Object fieldValue = field.get(value);
TypeAdapter t = jsonAdapterPresent ? typeAdapter
: new TypeAdapterRuntimeTypeWrapper(context, typeAdapter, fieldType.getType());
t.write(writer, fieldValue);
}
@Override
void read(JsonReader reader, Object value) throws IOException, IllegalAccessException {
//根据这个字段对应的Type获取对应的TypeAdapter,调用TypeAdapter的read读取fieldValue
Object fieldValue = typeAdapter.read(reader);
if (fieldValue != null || !isPrimitive) {
field.set(value, fieldValue);//给field设置fieldValue
}
}
@Override
public boolean writeField(Object value) throws IOException, IllegalAccessException {
if (!serialized) return false;
Object fieldValue = field.get(value);
return fieldValue != value; // avoid recursion for example for Throwable.cause
}
};
}
BoundField这个类的用途是将字段的名称和Field进行绑定,字段的名称可能是字段名或者是通过注解定义的名称。
Gson用ReflectiveTypeAdapterFactory通过反射解析json ,核心原理简而言之就是通过反射创建Java对象,循环遍历该对象的Field,并通过Field的set(Object,value)方法来对Java对象的Field赋值。 步骤:
- 获取type对应的默认构造器
- 通过Constructor的newInstance()来创建一个type类型的Java对象
- 解析json的键值对,获取key和value,
- 获取key对应的Field,通过Field的set(Object, value)方法设置value
小结
Gson解析成Java对象的实现原理:
1)注册自定义的或者Gson自己定义的TypeAdapter
2)将TypeAdapter封装成TypeAdapterFactory,并把此Factory添加到Gson的factories(List)中
3)通过fromJson方法最终调用getAdapter,遍历factories,获取fromJson的第二个参数type与之对应的TypeAdapterFactory,调用该Factory的create方法来创建一个TypeAdapter
4)调用TypeAdapter的read方法完成json到Java Object的转换。