在Gson之TypeAdapter的工作原理分析(1) 中分析了一下TypeAdapter的原理:先把TypeAdapter封装成TypeAdapterFactory然后通过TypeAdapterFactory的create创建TypeAdapter使用。在Gson中其实充斥了大量的TypeAdapterFactory,比如基本类型的TypeAdapter都有一个TypeAdapterFactory:
public static final TypeAdapterFactory BYTE_FACTORY
= newFactory(byte.class, Byte.class, BYTE);
public static final TypeAdapterFactory BOOLEAN_FACTORY
= newFactory(boolean.class, Boolean.class, BOOLEAN);
public static final TypeAdapterFactory SHORT_FACTORY
= newFactory(short.class, Short.class, SHORT);
//等等,还有其他的一些TypeAdapterFactory就不一一列举
public static <TT> TypeAdapterFactory newFactory(final Class<TT> unboxed, final Class<TT> boxed, final TypeAdapter<? super TT> typeAdapter) {
return new
() {
@SuppressWarnings("unchecked")
//TypeAdapterFactory接口的一定义的唯一的一个方法
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;
}
};
}
我们在自定义TypeAdapter的时候通过注册使用实际上就是先转换成TypeAdapterFactory然后在Gson的getAdapter方法中遍历TyperAdapterFactory,并调用create方法然后使用我们的TypeAdapter。能不能直接传我们自定义的TypeAdapterFactory呢?答案是确定的,因为GsonBuilder正好提供了这个方法:
public GsonBuilder registerTypeAdapterFactory(TypeAdapterFactory factory) {
factories.add(factory);
return this;
}
其实在我们用new Gson()这个Gson默认构造器的时候,其实调用了另外一个带参数的构造器进行初始化:
public Gson() {
this(Excluder.DEFAULT, FieldNamingPolicy.IDENTITY,
Collections.<Type, InstanceCreator<?>>emptyMap(), false, false, DEFAULT_JSON_NON_EXECUTABLE,
true, false, false, LongSerializationPolicy.DEFAULT,
Collections.<TypeAdapterFactory>emptyList());
}
带有参数的构造器的的其中一个作用就是为Gson对象的List factories 添加大量的Gson自定义的TypeAdapterFactory:
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.ENUM_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 ReflectiveTypeAdapterFactory(
constructorConstructor, fieldNamingPolicy, excluder));
this.factories = Collections.unmodifiableList(factories);
其实你也许有个小疑问,既然自己定义了TypeAdapter为什么还需要添加上面这些Factory,为此我专门修改了一下Gson的构造器:
public Gson(final Excluder excluder, final FieldNamingStrategy fieldNamingPolicy,
final Map<Type, InstanceCreator<?>> instanceCreators, boolean serializeNulls,
boolean complexMapKeySerialization, boolean generateNonExecutableGson, boolean htmlSafe,
boolean prettyPrinting, boolean serializeSpecialFloatingPointValues,
LongSerializationPolicy longSerializationPolicy,
List<TypeAdapterFactory> typeAdapterFactories,boolean myGosn) {
this.constructorConstructor = new ConstructorConstructor(instanceCreators);
this.serializeNulls = serializeNulls;
this.generateNonExecutableJson = generateNonExecutableGson;
this.htmlSafe = htmlSafe;
this.prettyPrinting = prettyPrinting;
List<TypeAdapterFactory> factories = new ArrayList<TypeAdapterFactory>();
//省略了上面添加Gson自定的Factory的方法
//直接添加自己的TypeAdapter封装的TypeFactory
factories.addAll(typeAdapterFactories);
this.factories = Collections.unmodifiableList(factories);
}
通过这种方式,也是可以直接调用你的TypeAdapter来完成你的任务的。具体为什么在GsonBuilder注册过自定义的Adapter的时候,还需要添加这些Gson自己的TypeAdapterFactory?关于这个问题在下一篇博客中将详细分析说明。
这篇就写到这儿,最后写一个自定义的TypeAdapter来解析一下一个json串(来源):
{
"isbn": "978-0321336781",
"title": "Java Puzzlers: Traps, Pitfalls, and Corner Cases",
"authors": [ { "id": 1, "name": "Joshua Bloch" }, { "id": 2, "name": "Neal Gafter" } ] }
对应的JavaBean:
Book {
private Author[] authors;
private String isbn;
private String title;
//getter and setter方法
}
Author {
private int id;
private String name;
//getter and setter方法
}
对应的TypeAdapter:
public class BookTypeAdapter extends TypeAdapter<Book> { @Override public Book read(final JsonReader in) throws IOException { final Book book = new Book(); in.beginObject(); while(in.hasNext()) {//遍历当前的jsonObject switch (in.nextName()) { case "isbn": book.setIsbn(in.nextString()); break; case "title": book.setTitle(in.nextString()); break; case "authors": final List<Author> list = new ArrayList<Author>(); in.beginArray(); while(in.hasNext()) {//这个是遍历json数组中是否还有下一个jsonObject对象 in.beginObject(); final Author author = new Author(); //这个循环是遍历当前JsonObject串的内容 while(in.hasNext()) { String authorObjNextName = in.nextName(); switch (authorObjNextName) { case "id": int id = in.nextInt(); author.setId(id); break; case "name": String name = in.nextString(); author.setName(name); break; } }//遍历完当前jsonObject对象 list.add(author); in.endObject(); }//循环遍历完当前的array book.setAuthors(list.toArray(new Author[list.size()])); in.endArray(); break; } } in.endObject(); return book; } @Override public void write(final JsonWriter out, final Book2 book) throws IOException { out.beginObject(); out.name("isbn").value(book.getIsbn()); out.name("title").value(book.getTitle()); out.name("authors").beginArray(); for(Author author:book.getAuthors()) { //开始写对象 out.beginObject(); out.name("id").value(author.getId()); out.name("name").value(author.getName()); out.endObject(); } out.endArray(); out.endObject(); } @Override public String toString() { return "BookTypeAdapter4"; } }