在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 typesfactories.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 typesfactories.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封装的TypeFactoryfactories.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> {@Overridepublic Book read(final JsonReader in) throws IOException {final Book book = new Book();in.beginObject();while(in.hasNext()) {//遍历当前的jsonObjectswitch (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();}//循环遍历完当前的arraybook.setAuthors(list.toArray(new Author[list.size()]));in.endArray();break;}}in.endObject();return book;}@Overridepublic 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();}@Overridepublic String toString() {return "BookTypeAdapter4";}
}

Gson之TypeAdapterFactory相关推荐

  1. android 代码混淆 gson,Android RecyclerView和Gson混淆问题

    RecyclerView 配置混淆 release打包后发现RecyclerView不显示数据, 推测是反射没有加混淆问题, 具体置如下 # When layoutManager xml attrib ...

  2. Gson源码解析和它的设计模式

    前言 之前一段时间,准备把糗百的项目中json解析的模块中的原生Json解析换成gson解析,工作比较繁杂,坑多,因此为了防止出错,我还对Gson做了一个源码分析.这一篇就是Gson源码分析的总结,同 ...

  3. Android Gson使用详解

    Json 是一种文本形式的数据交换格式,比 xml 更为轻量.Json 的解析和生成的方式很多,在 Android 平台上最常用的类库有 Gson 和 FastJson 两种,这里要介绍的是 Gson ...

  4. Gson 使用总结 高级用法

    Gson基本用法 参考:http://www.jianshu.com/p/e740196225a4 Gson提供了fromJson() 和toJson() 两个直接用于解析和生成的方法,前者实现反序列 ...

  5. Android—Gson原理解析

    JsonElement 抽象类 代表json串的某一个元素 某一个元素: JsonObject JsonArray JsonPrimitive(基本类型) JsonNull JsonElement的四 ...

  6. Java json序列化库gson(2)

    2019独角兽企业重金招聘Python工程师标准>>> 基于策略(自定义规则) 上面介绍的了3种排除字段的方法,说实话我除了@Expose以外,其它的都是只在Demo用上过,用得最多 ...

  7. Android系统(96)---Android 数据交换解析框架Gson使用详解

    Android 数据交换解析框架Gson使用详解 Json 是一种文本形式的数据交换格式,比 xml 更为轻量.Json 的解析和生成的方式很多,在 Android 平台上最常用的类库有 Gson 和 ...

  8. gson 解析int类型转换为double解决方案

    背景: Gson在使用gson.fromJson对json对象中带int类型的数据转换时候,会存在nt类型转换为double的情况,原因是Gson在解释数据过程中的number类型处理导致的:具体见O ...

  9. Gson int类型被转换成double问题解决(完美解决)

    一.问题复现 1.1.BaseResponse类 class BaseResponse<T>(val code: Int = -1,val message: String? = null ...

  10. Gson转换错误导致Int变为Double类型

    情况说明 需要解析的json {"status": 200,"msg": "OK","data": [{"id ...

最新文章

  1. 工作中InnoDB引擎数据库主从复制同步心得
  2. 再造人类生命的神奇细胞Human.Life.Our.Amazing.Cell
  3. mysql主从配置流程
  4. 计算机信息科学蔺泽浩,上海交通大学计算机科学与工程系(CSE)
  5. WhatFont——Google Chrome字体识别扩展
  6. Android硬件入门-照相机
  7. 【ENVI二次开发】关于批处理(Batch)模式与ENVI_DOIT的使用
  8. mac 使用js打开计算器_Numi for Mac(mac计算器软件)
  9. pycharm中设置鼠标滚动放大和缩小页面
  10. 美女直播这么火,那你知道怎么测试直播软件吗?
  11. CAD绘制填充,从中间挖去一块(网页版)
  12. 自己在用的KEIL颜色
  13. fu-liou radiative transfer model 学习日记(一)
  14. Kinect 开发 —— 深度信息(二)
  15. 用python实现12306抢票
  16. 三款Linux下最好的看图工具GPicView,sxiv,feh
  17. C++11实现多线程电梯运行
  18. 南邮离散数学试卷2023(含答案)
  19. [附源码]计算机毕业设计Python+uniapp智慧校园平台APP06l79(程序+lw+APP+远程部署)
  20. ygbook和ptcms哪个好_杰奇CMS 和 PTCMS 有什么区别? 为什么很多人选择杰奇?

热门文章

  1. 服务器不稳定补偿,《异化之地》服务器异常怎么解决 服务器不稳定官方补偿...
  2. 实战Python:利用Python实现基于终端的文本行编辑程序
  3. 爬虫:Python爬虫学习笔记之Urllib库
  4. 彻底搞懂使用MyBatis时为什么Dao层不需要@Repository
  5. onClick,onServerClick,onClientClick
  6. 论文笔记_S2D.44_自监督的从稀疏到稠密:用激光雷达和单目摄像机进行自监督深度补全
  7. 随手记_C++语法中的一些注意事项
  8. OpenCV版本与EmguCV版本匹配问题
  9. 浅谈混合精度训练imagenet
  10. 用简单Mask分类实现语义分割、实例分割“大一统”!FacebookUIUC开源MaskFormer