GsonConverterFactory源码分析

  • 前言

    前面我们分析了Retrofit的源码,知道了GsonConverterFactory是如何和Retrofit结合起来的。

  • GsonRequestBodyConverter

    先看请求入参如何转换,即通过handlers[p].apply(requestBuilder, args[p])来解析参数,以ParameterHandler.Body为例:

    static final class Body<T> extends ParameterHandler<T> {
      private final Method method;
      private final int p;
      private final Converter<T, RequestBody> converter;
    
      Body(Method method, int p, Converter<T, RequestBody> converter) {
        this.method = method;
        this.p = p;
        this.converter = converter;
      }
    
      @Override
      void apply(RequestBuilder builder, @Nullable T value) {
        if (value == null) {
          throw Utils.parameterError(method, p, "Body parameter value must not be null.");
        }
        RequestBody body;
        try {
          body = converter.convert(value);
        } catch (IOException e) {
          throw Utils.parameterError(method, e, p, "Unable to convert " + value + " to RequestBody");
        }
        builder.setBody(body);
      }
    }
    

    调用converter.convert(value)生成body,看一下converter(GsonRequestBodyConverter)的convert:

    final class GsonRequestBodyConverter<T> implements Converter<T, RequestBody> {
      private static final MediaType MEDIA_TYPE = MediaType.get("application/json; charset=UTF-8");
      private static final Charset UTF_8 = Charset.forName("UTF-8");
    
      private final Gson gson;
      private final TypeAdapter<T> adapter;
    
      GsonRequestBodyConverter(Gson gson, TypeAdapter<T> adapter) {
        this.gson = gson;
        this.adapter = adapter;
      }
    
      @Override
      public RequestBody convert(T value) throws IOException {
        Buffer buffer = new Buffer();
        Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8);
        JsonWriter jsonWriter = gson.newJsonWriter(writer);
        adapter.write(jsonWriter, value);
        jsonWriter.close();
        return RequestBody.create(MEDIA_TYPE, buffer.readByteString());
      }
    }
    
    • GsonResponseBodyConverter

    再来看返参转换,即通过OkHttpCall中execute调用的parseResponse(call.execute()):

    Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
      ResponseBody rawBody = rawResponse.body();
    
      // Remove the body's source (the only stateful object) so we can pass the response along.
      rawResponse =
          rawResponse
              .newBuilder()
              .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
              .build();
    
      int code = rawResponse.code();
      if (code < 200 || code >= 300) {
        try {
          // Buffer the entire body to avoid future I/O.
          ResponseBody bufferedBody = Utils.buffer(rawBody);
          return Response.error(bufferedBody, rawResponse);
        } finally {
          rawBody.close();
        }
      }
    
      if (code == 204 || code == 205) {
        rawBody.close();
        return Response.success(null, rawResponse);
      }
    
      ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
      try {
        T body = responseConverter.convert(catchingBody);
        return Response.success(body, rawResponse);
      } catch (RuntimeException e) {
        // If the underlying source threw an exception, propagate that rather than indicating it was
        // a runtime exception.
        catchingBody.throwIfCaught();
        throw e;
      }
    }
    

    调用responseConverter.convert(catchingBody)生成body,看一下responseConverter(GsonResponseBodyConverter)的convert:

    final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
      private final Gson gson;
      private final TypeAdapter<T> adapter;
    
      GsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {
        this.gson = gson;
        this.adapter = adapter;
      }
    
      @Override
      public T convert(ResponseBody value) throws IOException {
        JsonReader jsonReader = gson.newJsonReader(value.charStream());
        try {
          T result = adapter.read(jsonReader);
          if (jsonReader.peek() != JsonToken.END_DOCUMENT) {
            throw new JsonIOException("JSON document was not fully consumed.");
          }
          return result;
        } finally {
          value.close();
        }
      }
    }
    
  • 源码分析

    可以看到不管是write还是read,都需要adapter去做,adapter是什么呢?回到构建它们的地方:

    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(
        Type type, Annotation[] annotations, Retrofit retrofit) {
      TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
      return new GsonResponseBodyConverter<>(gson, adapter);
    }
    
    @Override
    public Converter<?, RequestBody> requestBodyConverter(
        Type type,
        Annotation[] parameterAnnotations,
        Annotation[] methodAnnotations,
        Retrofit retrofit) {
      TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
      return new GsonRequestBodyConverter<>(gson, adapter);
    }
    

    都是通过gson.getAdapter来获取adapter的,这里的type就是方法中每个参数的类型,TypeToken封装了一下:

    public static TypeToken<?> get(Type type) {
      return new TypeToken<Object>(type);
    }
    

    看一下gson的getAdapter做了什么:

    public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {
      TypeAdapter<?> cached = typeTokenCache.get(type == null ? NULL_KEY_SURROGATE : type);
      if (cached != null) {
        return (TypeAdapter<T>) cached;
      }
    
      Map<TypeToken<?>, FutureTypeAdapter<?>> threadCalls = calls.get();
      boolean requiresThreadLocalCleanup = false;
      if (threadCalls == null) {
        threadCalls = new HashMap<TypeToken<?>, FutureTypeAdapter<?>>();
        calls.set(threadCalls);
        requiresThreadLocalCleanup = true;
      }
    
      // the key and value type parameters always agree
      FutureTypeAdapter<T> ongoingCall = (FutureTypeAdapter<T>) threadCalls.get(type);
      if (ongoingCall != null) {
        return ongoingCall;
      }
    
      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;
          }
        }
        throw new IllegalArgumentException("GSON (" + GsonBuildConfig.VERSION + ") cannot handle " + type);
      } finally {
        threadCalls.remove(type);
    
        if (requiresThreadLocalCleanup) {
          calls.remove();
        }
      }
    }
    

    通过遍历factories调用factory.create(this, type)得到candidate,如果不为空就返回,那么factories从哪来的呢?在Gson的构造方法里得到答案:

    Gson(final Excluder excluder, final FieldNamingStrategy fieldNamingStrategy,
        final Map<Type, InstanceCreator<?>> instanceCreators, boolean serializeNulls,
        boolean complexMapKeySerialization, boolean generateNonExecutableGson, boolean htmlSafe,
        boolean prettyPrinting, boolean lenient, boolean serializeSpecialFloatingPointValues,
        LongSerializationPolicy longSerializationPolicy, String datePattern, int dateStyle,
        int timeStyle, List<TypeAdapterFactory> builderFactories,
        List<TypeAdapterFactory> builderHierarchyFactories,
        List<TypeAdapterFactory> factoriesToBeAdded) {
      this.excluder = excluder;
      this.fieldNamingStrategy = fieldNamingStrategy;
      this.instanceCreators = instanceCreators;
      this.constructorConstructor = new ConstructorConstructor(instanceCreators);
      this.serializeNulls = serializeNulls;
      this.complexMapKeySerialization = complexMapKeySerialization;
      this.generateNonExecutableJson = generateNonExecutableGson;
      this.htmlSafe = htmlSafe;
      this.prettyPrinting = prettyPrinting;
      this.lenient = lenient;
      this.serializeSpecialFloatingPointValues = serializeSpecialFloatingPointValues;
      this.longSerializationPolicy = longSerializationPolicy;
      this.datePattern = datePattern;
      this.dateStyle = dateStyle;
      this.timeStyle = timeStyle;
      this.builderFactories = builderFactories;
      this.builderHierarchyFactories = builderHierarchyFactories;
    
      List<TypeAdapterFactory> factories = new ArrayList<TypeAdapterFactory>();
    
      // 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);
    
      // 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);
    }
    

    可以看到factories的添加顺序,JsonElement和Object类型的会先尝试create(),然后是exclude被排除在外的,然后是用户添加的,再然后是默认的数据类型,最后是复合类型(集合、Map、JsonAdapter注解、枚举、反射)。

    需要注意的一点是,当用户调用GsonBuilder().registerTypeAdapter()或者GsonBuilder().registerTypeHierarchyAdapter()时,最后create方法:

    public Gson create() {
      List<TypeAdapterFactory> factories = new ArrayList<TypeAdapterFactory>(this.factories.size() + this.hierarchyFactories.size() + 3);
      factories.addAll(this.factories);
      Collections.reverse(factories);
    
      List<TypeAdapterFactory> hierarchyFactories = new ArrayList<TypeAdapterFactory>(this.hierarchyFactories);
      Collections.reverse(hierarchyFactories);
      factories.addAll(hierarchyFactories);
    
      addTypeAdaptersForDate(datePattern, dateStyle, timeStyle, factories);
    
      return new Gson(excluder, fieldNamingPolicy, instanceCreators,
          serializeNulls, complexMapKeySerialization,
          generateNonExecutableJson, escapeHtmlChars, prettyPrinting, lenient,
          serializeSpecialFloatingPointValues, longSerializationPolicy,
          datePattern, dateStyle, timeStyle,
          this.factories, this.hierarchyFactories, factories);
    }
    

    可以看到,factories和hierarchyFactories都是reverse倒序的,所以你手动添加的adapter中后添加的会先调用,而且registerTypeHierarchyAdapter添加的比registerTypeAdapter添加的要晚调用。

    public GsonBuilder registerTypeAdapter(Type type, Object typeAdapter) {
      $Gson$Preconditions.checkArgument(typeAdapter instanceof JsonSerializer<?>
          || typeAdapter instanceof JsonDeserializer<?>
          || typeAdapter instanceof InstanceCreator<?>
          || typeAdapter instanceof TypeAdapter<?>);
      if (typeAdapter instanceof InstanceCreator<?>) {
        instanceCreators.put(type, (InstanceCreator) typeAdapter);
      }
      if (typeAdapter instanceof JsonSerializer<?> || typeAdapter instanceof JsonDeserializer<?>) {
        TypeToken<?> typeToken = TypeToken.get(type);
        factories.add(TreeTypeAdapter.newFactoryWithMatchRawType(typeToken, typeAdapter));
      }
      if (typeAdapter instanceof TypeAdapter<?>) {
        factories.add(TypeAdapters.newFactory(TypeToken.get(type), (TypeAdapter)typeAdapter));
      }
      return this;
    }
    
    public GsonBuilder registerTypeHierarchyAdapter(Class<?> baseType, Object typeAdapter) {
      $Gson$Preconditions.checkArgument(typeAdapter instanceof JsonSerializer<?>
          || typeAdapter instanceof JsonDeserializer<?>
          || typeAdapter instanceof TypeAdapter<?>);
      if (typeAdapter instanceof JsonDeserializer || typeAdapter instanceof JsonSerializer) {
        hierarchyFactories.add(TreeTypeAdapter.newTypeHierarchyFactory(baseType, typeAdapter));
      }
      if (typeAdapter instanceof TypeAdapter<?>) {
        factories.add(TypeAdapters.newTypeHierarchyFactory(baseType, (TypeAdapter)typeAdapter));
      }
      return this;
    }
    

    通过代码得知,除了调用顺序,registerTypeAdapter要多一个InstanceCreator类型的Adapter设置。

    以registerTypeAdapter为例,自定义一个:

    private class IntegerDefaultAdapter : JsonSerializer<Int>, JsonDeserializer<Int> {
        @Throws(JsonParseException::class)
        override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): Int? {
            try {
                //定义为int类型,如果后台返回""或者null,则返回0
                if ("" == json.asString || "null" == json.asString) {
                    return 0
                }
            } catch (ignore: Exception) {
            }
    
            try {
                return json.asInt
            } catch (e: NumberFormatException) {
                throw JsonSyntaxException(e)
            }
    
        }
    
        override fun serialize(src: Int?, typeOfSrc: Type, context: JsonSerializationContext): JsonElement {
            return JsonPrimitive(src!!)
        }
    }
    
    factories.add(TreeTypeAdapter.newFactoryWithMatchRawType(typeToken, typeAdapter))
    
    public static TypeAdapterFactory newFactoryWithMatchRawType(
        TypeToken<?> exactType, Object typeAdapter) {
      // only bother matching raw types if exact type is a raw type
      boolean matchRawType = exactType.getType() == exactType.getRawType();
      return new SingleTypeFactory(typeAdapter, exactType, matchRawType, null);
    }
    
    SingleTypeFactory(Object typeAdapter, TypeToken<?> exactType, boolean matchRawType,
        Class<?> hierarchyType) {
      serializer = typeAdapter instanceof JsonSerializer
          ? (JsonSerializer<?>) typeAdapter
          : null;
      deserializer = typeAdapter instanceof JsonDeserializer
          ? (JsonDeserializer<?>) typeAdapter
          : null;
      $Gson$Preconditions.checkArgument(serializer != null || deserializer != null);
      this.exactType = exactType;
      this.matchRawType = matchRawType;
      this.hierarchyType = hierarchyType;
    }
    

    当调用create时:

    @Override
    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
      boolean matches = exactType != null
          ? exactType.equals(type) || matchRawType && exactType.getType() == type.getRawType()
          : hierarchyType.isAssignableFrom(type.getRawType());
      return matches
          ? new TreeTypeAdapter<T>((JsonSerializer<T>) serializer,
              (JsonDeserializer<T>) deserializer, gson, type, this)
          : null;
    }
    

    adapter.write和adapter.read就是:

    @Override public T read(JsonReader in) throws IOException {
      if (deserializer == null) {
        return delegate().read(in);
      }
      JsonElement value = Streams.parse(in);
      if (value.isJsonNull()) {
        return null;
      }
      return deserializer.deserialize(value, typeToken.getType(), context);
    }
    
    @Override public void write(JsonWriter out, T value) throws IOException {
      if (serializer == null) {
        delegate().write(out, value);
        return;
      }
      if (value == null) {
        out.nullValue();
        return;
      }
      JsonElement tree = serializer.serialize(value, typeToken.getType(), context);
      Streams.write(tree, out);
    }
    

    这就调用到了自定义的serialize中,最后是TypeAdapters.JSON_ELEMENT:

    public static final TypeAdapter<JsonElement> JSON_ELEMENT = new TypeAdapter<JsonElement>() {
      @Override public JsonElement read(JsonReader in) throws IOException {
        switch (in.peek()) {
        case STRING:
          return new JsonPrimitive(in.nextString());
        case NUMBER:
          String number = in.nextString();
          return new JsonPrimitive(new LazilyParsedNumber(number));
        case BOOLEAN:
          return new JsonPrimitive(in.nextBoolean());
        case NULL:
          in.nextNull();
          return JsonNull.INSTANCE;
        case BEGIN_ARRAY:
          JsonArray array = new JsonArray();
          in.beginArray();
          while (in.hasNext()) {
            array.add(read(in));
          }
          in.endArray();
          return array;
        case BEGIN_OBJECT:
          JsonObject object = new JsonObject();
          in.beginObject();
          while (in.hasNext()) {
            object.add(in.nextName(), read(in));
          }
          in.endObject();
          return object;
        case END_DOCUMENT:
        case NAME:
        case END_OBJECT:
        case END_ARRAY:
        default:
          throw new IllegalArgumentException();
        }
      }
    
      @Override public void write(JsonWriter out, JsonElement value) throws IOException {
        if (value == null || value.isJsonNull()) {
          out.nullValue();
        } else if (value.isJsonPrimitive()) {
          JsonPrimitive primitive = value.getAsJsonPrimitive();
          if (primitive.isNumber()) {
            out.value(primitive.getAsNumber());
          } else if (primitive.isBoolean()) {
            out.value(primitive.getAsBoolean());
          } else {
            out.value(primitive.getAsString());
          }
    
        } else if (value.isJsonArray()) {
          out.beginArray();
          for (JsonElement e : value.getAsJsonArray()) {
            write(out, e);
          }
          out.endArray();
    
        } else if (value.isJsonObject()) {
          out.beginObject();
          for (Map.Entry<String, JsonElement> e : value.getAsJsonObject().entrySet()) {
            out.name(e.getKey());
            write(out, e.getValue());
          }
          out.endObject();
    
        } else {
          throw new IllegalArgumentException("Couldn't write " + value.getClass());
        }
      }
    };
    

    至此,GsonConverter的应用过程就结束了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,616评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,020评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,078评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,040评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,154评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,265评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,298评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,072评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,491评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,795评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,970评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,654评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,272评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,985评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,815评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,852评论 2 351

推荐阅读更多精彩内容