Gson源码之序列化(Java Array转String)

通过Gson将Java Array(数组)转换为String的入口是toJson(),那它到底做了什么?

1.Gson的构造函数主要是初始化factories (TypeAdapterFactory 集合),便于在getAapter()根据数据类型返回对应的TypeAdapterFactory,从而获取对应的TypeAdapter进行序列化和反序列化。 toJson()是序列化入口,首先会判断传入的数据是不是空,如为空则调用参数为JsonElement的toJson()方法;若不为空则调用传入Object和Class参数的toJson()方法

	 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(Excluder excluder, FieldNamingStrategy fieldNamingStrategy,
	      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;//html转义
	    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;
	//TypeAdapter的工厂列表
	    List<TypeAdapterFactory> factories = new ArrayList<TypeAdapterFactory>();
	    //以下都是往工厂列表加入TypeAdapterFactory
	    // 构建不能被重载的TypeAdapter
	    // built-in type adapters that cannot be overridden
	    factories.add(TypeAdapters.JSON_ELEMENT_FACTORY);
	    factories.add(ObjectTypeAdapter.FACTORY);
	    // 排除器必须在所有的用于自定义的typeAdapter之前
	    // the excluder must precede all adapters that handle user-defined types
	    factories.add(excluder);
	    //用户自定义的typeAdapter工厂
	    // users' type adapters
	    factories.addAll(factoriesToBeAdded);
	    //以下为默认的TypeAdapter
	    // 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);
	//复合的TypeAdapter
	    // 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(//最后添加反射机制用的factory
	        constructorConstructor, fieldNamingStrategy, excluder, jsonAdapterFactory));
	
	    this.factories = Collections.unmodifiableList(factories);
	  }




	  public String toJson(Object src) {
	    if (src == null) {
	      return toJson(JsonNull.INSTANCE);
	    }
	    return toJson(src, src.getClass());
	  }

1.1.1 先看看数据为空的情况。当数据为空时,先调用参数为JsonElement的toJson()。首先会创建一个StringWriter,然后将JsonElement和StringWriter传入到toJson()

	  public String toJson(JsonElement jsonElement) {
	    StringWriter writer = new StringWriter();
	    toJson(jsonElement, writer);
	    return writer.toString();
	  }

1.1.2 在方法中创建一个JsonWriter, JsonWriter将StringWriter进行包装,然后将其传入到toJson()中

	  public void toJson(JsonElement jsonElement, Appendable writer) throws JsonIOException {
	    try {
	      JsonWriter jsonWriter = newJsonWriter(Streams.writerForAppendable(writer));
	      toJson(jsonElement, jsonWriter);
	    } catch (IOException e) {
	      throw new JsonIOException(e);
	    }
	  }
	  
    //默认情况下generateNonExecutableJson和prettyPrinting为false,所以没有做其他操作,只是设置了serializeNulls,默认为false  
    public JsonWriter newJsonWriter(Writer writer) throws IOException {
	    if (generateNonExecutableJson) {
	      writer.write(JSON_NON_EXECUTABLE_PREFIX);
	    }
	    JsonWriter jsonWriter = new JsonWriter(writer);
	    if (prettyPrinting) {
	      jsonWriter.setIndent("  ");
	    }
	    jsonWriter.setSerializeNulls(serializeNulls);
	    return jsonWriter;
    }

1.1.3 获取writer之前的配置信息,然后为其配置信息,之后调用Streams.write(jsonElement, writer)进行写入,最后把之前的配置信息再次配置进去

	      public void toJson(JsonElement jsonElement, JsonWriter writer) throws JsonIOException {
	    boolean oldLenient = writer.isLenient();
	    writer.setLenient(true);
	    boolean oldHtmlSafe = writer.isHtmlSafe();
	    writer.setHtmlSafe(htmlSafe);
	    boolean oldSerializeNulls = writer.getSerializeNulls();
	    writer.setSerializeNulls(serializeNulls);
	    try {
	      Streams.write(jsonElement, writer);
	    } catch (IOException e) {
	      throw new JsonIOException(e);
	    } catch (AssertionError e) {
	      AssertionError error = new AssertionError("AssertionError (GSON " + GsonBuildConfig.VERSION + "): " + e.getMessage());
	      error.initCause(e);
	      throw error;
	    } finally {
	      writer.setLenient(oldLenient);
	      writer.setHtmlSafe(oldHtmlSafe);
	      writer.setSerializeNulls(oldSerializeNulls);
	    }
	  }

1.1.4 该方法是Streams类中的方法,它主要调用TypeAdapters中JSON_ELEMENT的writer方法进行写入,JSON_ELEMENT是TypeAdapter类型的

	  public static void write(JsonElement element, JsonWriter writer) throws IOException {
	    TypeAdapters.JSON_ELEMENT.write(writer, element);
	  }

1.1.5 JSON_ELEMENT位于TypeAdapters,它是TypeAdapter的子类,重写了read和writer方法,那么我们重点看writer方法。首先判断数据是否是空类型,若是的话调用writer.nullValue(),直接写入null字符串;若数据是原始数据类型,判断若是number类型,则调用writer.value()将值转换为number进行写入,若是boolean类型,则调用writer.value()将值转换为boolean进行写入,若是原始类型的其他类型,则以String类型进行写入;若value是jsonArray类型的,则以数组的结构进行写入;若value是JsonObject类型的,则以Object的结构进行写入。但是我们设置value是JsonNull类型,所以是直接写入null,这就是当我们传入的数据是null时的执行流程

	 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 {

      //若JsonElement为空或者JsonElement的类型为JsonNull,则直接调用writer的nullValue() 
      if (value == null || value.isJsonNull()) {
        out.nullValue();
      //若JsonElement的类型是JsonPrimitive,判断JsonPrimitive的数据是number类型,则将数据转换为number进行写入;若JsonPrimitive的数据是boolean类型,则将数据转换为boolean进行写入;JsonPrimitive的数据是其它类型,则将数据转换为String进行写入
      } 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());
        }

      //若JsonElement的类型是JsonArray,则按照数组的结构进行数据写入
      } else if (value.isJsonArray()) {
        out.beginArray();
        for (JsonElement e : value.getAsJsonArray()) {
          write(out, e);
        }
        out.endArray();

	  //若JsonElement的类型是JsonObject,则按照object的结构进行数据写入
      } 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());
      }
    }
    };

1.2.1 第二种情况是若传入的数据不为空。则调用参数为Object和Type类型的toJson()方法。在toJson()中创建一个StringWriter对象,之后调用参数为Object,type,writer的toJson()方法进行数据写入,写入完成之后调用writer.toString()将写入的数据以String的形式返回

	    public String toJson(Object src, Type typeOfSrc) {
	    StringWriter writer = new StringWriter();
	    toJson(src, typeOfSrc, writer);
	    return writer.toString();
	  }

1.2.2 在参数为Object,Type,Writer的toJson()方法,创建一个JsonWriter对象,并将Appendable封装到JsonWriter中,之后调用参数为Object,Type,JsonWriter的toJson()方法

	    public void toJson(Object src, Type typeOfSrc, Appendable writer) throws JsonIOException {
	    try {
	      JsonWriter jsonWriter = newJsonWriter(Streams.writerForAppendable(writer));
	      toJson(src, typeOfSrc, jsonWriter);
	    } catch (IOException e) {
	      throw new JsonIOException(e);
	    }
	  }

1.2.3 在参数为Object,Type,JsonWriter的toJson()方法中进行数据写入,首先TypeToken通过的get()获取写入的Object的typeToken,然后遍历factories集合,以typeToken为参数调用factory.create(this, type)获取对应的typeAdapter,当获取到对应数据类型的typeAdapter,然后调用typeAdapter.writer()进行写入。对于基本数据类型和数组类型gson已经内置,这里使用数组对应的TypeAdapter,将通过CollectionTypeAdapterFactory进行数据的读写。其中factories是typeAdapterFactory集合,在Gson的构造函数添加了各种内置的数据类型的typeAdapter,以及自定义的typeAdapter。下面我们来看CollectionTypeAdapterFactory是如何进行数据的写入的

	 public void toJson(Object src, Type typeOfSrc, JsonWriter writer) throws JsonIOException {
	    TypeAdapter<?> adapter = getAdapter(TypeToken.get(typeOfSrc));
	    boolean oldLenient = writer.isLenient();
	    writer.setLenient(true);
	    boolean oldHtmlSafe = writer.isHtmlSafe();
	    writer.setHtmlSafe(htmlSafe);
	    boolean oldSerializeNulls = writer.getSerializeNulls();
	    writer.setSerializeNulls(serializeNulls);
 
	    try {
	 
	      ((TypeAdapter<Object>) adapter).write(writer, src);
	    } catch (IOException e) {
	      throw new JsonIOException(e);
	    } catch (AssertionError e) {
	      AssertionError error = new AssertionError("AssertionError (GSON " + GsonBuildConfig.VERSION + "): " + e.getMessage());
	      error.initCause(e);
	      throw error;
	    } finally {
	
	       writer.setLenient(oldLenient);
	       writer.setHtmlSafe(oldHtmlSafe);
	       writer.setSerializeNulls(oldSerializeNulls);
	    }
    }
	  
	  
	  
	    public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {
	     //typeTokenCache 是 Gson 中的一个 map 对象,用于储存 TypeAdapter
		  //typeTokenCache 是一个 Gson 中各个线程公用的一个缓存池
		  TypeAdapter<?> cached = typeTokenCache.get(type == null ? 				NULL_KEY_SURROGATE : type);
	    if (cached != null) {
	      //如果本身就有储存了,就直接返回
		    return (TypeAdapter<T>) cached;
		  }

			//calls 是一个 ThreadLocal 对象
			 //ThreadLocal 是 Gson 中单个线程使用的缓存池,在里面存入的对象会在 				finally 代码块中清空掉
			  Map<TypeToken<?>, FutureTypeAdapter<?>> threadCalls = calls.get();
		  //判断是否需要清空 ThreadLocal
	 	  boolean requiresThreadLocalCleanup = false;
		  if (threadCalls == null) {
		    threadCalls = new HashMap<TypeToken<?>, FutureTypeAdapter<?>>();
		   calls.set(threadCalls);
		   //这里存入了对象,所以需要清空 ThreadLocal
		   requiresThreadLocalCleanup = true;
		  }

		  //如果存在对象,就会在这里取用出来并返回
		  //FutureTypeAdapter 是一个门面模式的应用,其实本质是使用内部的 				TypeAdapter 去处理业务
		   //如果内部没有存入实际处理业务的 TypeAdapter,就会报错
		   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 循环,用于从 Gson 初始化的时候储存的列表中获取到对应的 TypeAdapter
	      for (TypeAdapterFactory factory : factories) {
	        //TypeAdapter 的 create(...) 方法对于不是对应类型的参数会返回 null
	        //Log.i("TypeAdapterFactory","TypeAdapterFactory:"+factory);

	        TypeAdapter<T> candidate = factory.create(this, type);
	        if (candidate != null) {
	          //在此处会存入业务处理的 TypeAdapter
	          call.setDelegate(candidate);
	          //在此处存入公用缓存
	          typeTokenCache.put(type, candidate);
	          Log.i(TAG,"采用的factory1111:"+factory+"-->"+candidate);
	
	          return candidate;
	        }
	      }
			   throw new IllegalArgumentException("GSON (" + 					GsonBuildConfig.VERSION + ") cannot handle " + type);
		} finally {
		    //清除 ThreadLocal 缓存
			  threadCalls.remove(type);
			  if (requiresThreadLocalCleanup) {
 				   calls.remove();
		   }
					   }
		  }

1.2.4 CollectionTypeAdapterFactory实现了TypeAdapterFactory接口,而TypeAdapterFactory我们知道是一个TypeAdapter的创建工厂,所以CollectionTypeAdapterFactory会重写create方法创建一个TypeAdapter进行数据的读写操作

CollectionTypeAdapterFactory的构造函数有1个参数

  ConstructorConstructor:是一个专门根据tokenType的泛型类型来构建对应的泛型类型对象,用于在read过程中创建需要的真正的对象

create():通过constructorConstructor.get(type)方法获取ObjectConstructor对象,ObjectConstructor可以在read中创建对应的Collection(集合)对象 ;通过 G s o n Gson GsonTypes.getCollectionElementType(type, rawType)获取集合的元素类型;通过gson.getAdapter(TypeToken.get(elementType))根据集合的元素数据类型返回对应的的TypeAdapter,若元素是String类型的,则会采用TypeAdaptets中对应的String类型的TypeAdapter,若集合中的元素是我们自己定义的Java Object,同时在Json数组中都是由一个个Json Object构成, 所以会使用ObjectTypeAdapter

CollectionTypeAdapterFactory内部构建了一个TypeAdapter专门用来进行序列化和反序列的

            Gson:用于返回集合元素应该使用的TypeAdapter
            
            elementType:表明集合中的元素类型
            
            elementTypeAdapter:集合元素的TypeAdapter
                         
            ObjectConstructor:用于构建集合对象,在TypeAdapter的read()中被使用
            
        
            write(JsonWriter out, T value):用于序列化操作(Java Array转Json),在写入之前调用out.beginArray()方法,该方法主要用于写入json字符串的的"["符号,之后遍历客户端传递过来的collection集合,通过elementTypeAdapter.write(out, element)将一个个元素进行写入,集合遍历完成之后了,表示数据写入完成,最后调用out.endArray()写入结束符号"]",那么整个Java Array就被转换为一个标准的json形式的字符串了
            
		    read(JsonReader in):用于进行反序列化操作(Json转换为Java Array)。首先会调用constructor.construct()创建Java Array的实例对象,然后调用in.beginArray()设置状态值为EMPTY_ARRAY,JsonReader在读取的时候会根据不同的状态进行不同的操作,然后调用in.hasNext()判断是否有下一个数据,若有的话调用elementTypeAdapter.read(in)根据数据元素对应的TypeAdapter进行read()。当所有的数据都写入完成之后,调用in.endArray()重置状态           

ObjectTypeAdapter时Object类型的TypeAdapter,因为Json数组都是由一个个Json对象构建而成,所以在CollectionTypeAdapterFactory在遍历collections,调用 elementTypeAdapter.write(out, element)进行单个元素的写入的时候,就是使用的此TypeAdapter

           Gson: 通过构造函数传递进来,用于调用getAdapter()获取元素对应的解析器
           
           write(JsonWriter out, Object value):对传递进来的值进行序列化,但是它不直接参与序列化操作,而是根据传递的参数值的class对象来获取typeAdapter,通过获取的typeAdapter的write(typeAdapter.write(out, value))j进行真正的序列化操作
           
           read(JsonReader in):用于进行反序列化操作。获取当前数据类型,根据不同的数据类型进行读取操作

源码

		public final class CollectionTypeAdapterFactory implements TypeAdapterFactory {
		  private final ConstructorConstructor constructorConstructor;
		
		  public CollectionTypeAdapterFactory(ConstructorConstructor constructorConstructor) {
		    this.constructorConstructor = constructorConstructor;
		  }
		
		  @Override
		  public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
		    Type type = typeToken.getType();
		
		    Class<? super T> rawType = typeToken.getRawType();
		    if (!Collection.class.isAssignableFrom(rawType)) {
		      return null;
		    }
		
		    Type elementType = $Gson$Types.getCollectionElementType(type, rawType);
		    TypeAdapter<?> elementTypeAdapter = gson.getAdapter(TypeToken.get(elementType));
		    ObjectConstructor<T> constructor = constructorConstructor.get(typeToken);
		
		    @SuppressWarnings({"unchecked", "rawtypes"}) // create() doesn't define a type parameter
		    TypeAdapter<T> result = new Adapter(gson, elementType, elementTypeAdapter, constructor);
		    return result;
		  }
		
		  private static final class Adapter<E> extends TypeAdapter<Collection<E>> {
		    private final TypeAdapter<E> elementTypeAdapter;
		    private final ObjectConstructor<? extends Collection<E>> constructor;
		
		    public Adapter(Gson context, Type elementType,
		        TypeAdapter<E> elementTypeAdapter,
		        ObjectConstructor<? extends Collection<E>> constructor) {
		      this.elementTypeAdapter =
		          new TypeAdapterRuntimeTypeWrapper<E>(context, elementTypeAdapter, elementType);
		      this.constructor = constructor;
		    }
		
		    @Override public Collection<E> read(JsonReader in) throws IOException {
		      if (in.peek() == JsonToken.NULL) {
		        in.nextNull();
		        return null;
		      }
		
		      Collection<E> collection = constructor.construct();
		      in.beginArray();
		      while (in.hasNext()) {
		        E instance = elementTypeAdapter.read(in);
		        collection.add(instance);
		      }
		      in.endArray();
		      return collection;
		    }
		
		    @Override public void write(JsonWriter out, Collection<E> collection) throws IOException {
		      if (collection == null) {
		        out.nullValue();
		        return;
		      }
		
		      out.beginArray();
		      for (E element : collection) {
		        elementTypeAdapter.write(out, element);
		      }
		      out.endArray();
		    }
			  }
			}





		    public final class ObjectTypeAdapter extends TypeAdapter<Object> {
		  //工厂类
		  public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
		    @SuppressWarnings("unchecked")
		    @Override public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
		      if (type.getRawType() == Object.class) { //该工厂用来创建Object类型的TypeAdapter
		        return (TypeAdapter<T>) new ObjectTypeAdapter(gson);
		      }
		      return null;
		    }
		  };
		
		  private final Gson gson;
		
		  ObjectTypeAdapter(Gson gson) {
		    this.gson = gson;
		  }
		
		  @Override public Object read(JsonReader in) throws IOException {
		    JsonToken token = in.peek();//查看元素类型
		    switch (token) {
		    case BEGIN_ARRAY:
		      List<Object> list = new ArrayList<Object>();
		      in.beginArray();//开始标识
		      while (in.hasNext()) {//还有下一个元素?
		        list.add(read(in));
		      }
		      in.endArray();//结束标识
		      return list;
		
		    case BEGIN_OBJECT://对象
		      Map<String, Object> map = new LinkedTreeMap<String, Object>();
		      in.beginObject();
		      while (in.hasNext()) {
		        map.put(in.nextName(), read(in));
		      }
		      in.endObject();
		      return map;
		
		    case STRING:
		      return in.nextString();
		
		    case NUMBER:
		      return in.nextDouble();
		
		    case BOOLEAN:
		      return in.nextBoolean();
		
		    case NULL:
		      in.nextNull();
		      return null;
		
		    default:
		      throw new IllegalStateException();
		    }
		  }
		
		  @SuppressWarnings("unchecked")
		  @Override public void write(JsonWriter out, Object value) throws IOException {
		    if (value == null) {
		      out.nullValue();
		      return;
		    }
		    //gson.getAdapter获取对应类型的TypeAdapter
		    TypeAdapter<Object> typeAdapter = (TypeAdapter<Object>) gson.getAdapter(value.getClass());
		    if (typeAdapter instanceof ObjectTypeAdapter) {
		      out.beginObject();
		      out.endObject();
		      return;
		    }
		
		    typeAdapter.write(out, value);
			  }
			}

1.2.5 从上面我们看到在序列化过程中,首先会根据客户端传递过来的Java Array的真实类型来获取对应的TypeAdapterFactory,TypeAdapterFactory会有一个对应的typeAdapter,调用这个typeAdapter的write()方法就可实现序列化操作,而在write方法中会循环遍历Collection集合,每一个元素都会有对应的typeAdapter,调用元素的typeAdapter的write方法进行元素的序列化操作,那么每一个元素就会进行具体元素的序列化操做,以此来完成整个数组的序列化操作

1.2.6 在Gson的序列化操作过程中最终是通过JsonWriter将Java Array转换为一个Json的字符串形式,JsonWriter中含有各种进行序列化的操作

    public class JsonWriter implements Closeable, Flushable {
		
		
	       private static final String[] REPLACEMENT_CHARS;
		  private static final String[] HTML_SAFE_REPLACEMENT_CHARS;
		  static {
		    REPLACEMENT_CHARS = new String[128];
		    for (int i = 0; i <= 0x1f; i++) {
		      REPLACEMENT_CHARS[i] = String.format("\\u%04x", (int) i);
		    }
		    REPLACEMENT_CHARS['"'] = "\\\"";
		    REPLACEMENT_CHARS['\\'] = "\\\\";
		    REPLACEMENT_CHARS['\t'] = "\\t";
		    REPLACEMENT_CHARS['\b'] = "\\b";
		    REPLACEMENT_CHARS['\n'] = "\\n";
		    REPLACEMENT_CHARS['\r'] = "\\r";
		    REPLACEMENT_CHARS['\f'] = "\\f";
		    HTML_SAFE_REPLACEMENT_CHARS = REPLACEMENT_CHARS.clone();
		    HTML_SAFE_REPLACEMENT_CHARS['<'] = "\\u003c";
		    HTML_SAFE_REPLACEMENT_CHARS['>'] = "\\u003e";
		    HTML_SAFE_REPLACEMENT_CHARS['&'] = "\\u0026";
		    HTML_SAFE_REPLACEMENT_CHARS['='] = "\\u003d";
		    HTML_SAFE_REPLACEMENT_CHARS['\''] = "\\u0027";
		  }
		
		  /** The output data, containing at most one top-level array or object. */
		  private final Writer out;
		
		  private int[] stack = new int[32];
		  private int stackSize = 0;
		  {
		    //在数组的第一位写入EMPTY_DOCUMENT 并将stackSize变为1
		    push(EMPTY_DOCUMENT);
		  }
		
		
		  /**
		   * 一个字符串  在默认中是null  在格式化打印中是空格  主要是在格式话字符串后
		   */
		  private String indent=" ";
		
		  /**
		   * The name/value separator; either ":" or ": ".
		   */
		  private String separator = ":";
		
		  private boolean lenient;
		
		  private boolean htmlSafe;
		
		  private String deferredName;
		
		  private boolean serializeNulls = true;

		
		
		
		  public JsonWriter nullValue() throws IOException {
		    if (deferredName != null) {
		      //若属性名不为空 而且可以序列化空数据值属性  则写入属性名
		      if (serializeNulls) {
		        writeDeferredName();
		      } else {
		        deferredName = null;
		        return this; // skip the name and the value
		      }
		    }
		    //根据对应的状态 进行一些操作 包含修改状态 换行 写入逗号或分号等
		    beforeValue();
		    //写入null
		    out.write("null");
		    return this;
		  }
		
		  public JsonWriter beginObject() throws IOException {

		    //这个方法主要的作用是在不同的 object 之间加逗号
		    //如果是起始第一个 object 就不需要了,会直接跳过
		    writeDeferredName();
		    JsonWriter jsonWriter=open(EMPTY_OBJECT, '{');
		 
		
		    return  jsonWriter;
		  }
		  
		    public JsonWriter beginArray() throws IOException {
				    writeDeferredName();
				    return open(EMPTY_ARRAY, '[');
			  }


				 public JsonWriter endArray() throws IOException {
				    return close(EMPTY_ARRAY, NONEMPTY_ARRAY, ']');
				  }
		  
		  
		    public JsonWriter endObject() throws IOException {
                            JsonWriter jsonWriter=close(EMPTY_OBJECT, NONEMPTY_OBJECT, '}');
			 
			       return jsonWriter;
			  }

		  
		  
		 private JsonWriter open(int empty, char openBracket) throws IOException {
			    //该方法会使用 stack 中最新的指令进行操作
			    //根据getPeek()获取stacksize对应的值 然后根据其当前状态标识下一个状态是什么
			    beforeValue();
			    //push(...) 方法会检查 stack 数组的容积,适时进行扩容,并把传入的指令存放到数组中
			    push(empty);
			    //写入字符串
			    out.write(openBracket);
			    return this;
			  }
		

			  private void beforeValue() throws IOException {
		    //peek() 方法会根据 stack 数组的指令获取到下一个要操作的字符类型
		    //会从stack数组中根据static 索引位置值 取对应的值
		    switch (peek()) {
		      case NONEMPTY_DOCUMENT://7  表示文档是一个数组或对象
		        if (!lenient) {
		          throw new IllegalStateException(
		                  "JSON must have only one top-level value.");
		        }
		      case EMPTY_DOCUMENT://6  未启动任何对象或数组
		        //replaceTop(...) 方法会将 stack 最新的指令更新成传入的参数
		        //在begin
		        replaceTop(NONEMPTY_DOCUMENT);
		        break;
		
		      case EMPTY_ARRAY://1 若数组是空  不需要加逗号
		        replaceTop(NONEMPTY_ARRAY);
		        //换行
		        newline();
		        break;
		      case NONEMPTY_ARRAY://2 若数组有一个元素以上 需要在下一个元素之前加逗号和换行符
		        out.append(',');
		        newline();
		        break;
		      case DANGLING_NAME://4 当对象key 写入之后  需要加入分号 后面就是value值
		        //separator 即为 ":" (冒号)
		        out.append(separator);
		        replaceTop(NONEMPTY_OBJECT);
		        break;
		      default:
		        throw new IllegalStateException("Nesting problem.");
		    }
		  }


				  private void beforeName() throws IOException {
				    int context = peek();
				 
				    if (context == NONEMPTY_OBJECT) { // first in object
				      Log.i("beginObject","beforeName 写入逗号:"+out.toString());
				
				      out.write(',');
				    } else if (context != EMPTY_OBJECT) { // not in an object!
				      throw new IllegalStateException("Nesting problem.");
				    }
				    //1.第一次写入属性名  通过peek()得到状态值为EMPTY_OBJECT  而且indent为空 所以newline()没做任何操作
				    //之后将stackSize-1位置的状态设置为DANGLING_NAME
				    //2.第二次写入的时候  通过peek()的到状态值为NONEMPTY_OBJECT  此时写入逗号,之后和第一次一样newline()没做任何操作
				    //再次将之后将stackSize-1位置的状态设置为DANGLING_NAME
				    //如此重复
				
				    //
				
				    newline();
				 
				    replaceTop(DANGLING_NAME);
				  }
				
				  private int peek() {
				    if (stackSize == 0) {
				      throw new IllegalStateException("JsonWriter is closed.");
				    }
				    return stack[stackSize - 1];
				  }
				
				 private void replaceTop(int topOfStack) {
				    stack[stackSize - 1] = topOfStack;
				  }
				
				
				  private void newline() throws IOException {
				 
				    //indent一般为空格
				    if (indent == null) {
				      return;
				    }
				
				    //换行
				    out.write('\n');
				 
				    for (int i = 1, size = stackSize; i < size; i++) {
				      out.write(indent);
				 
				    }
				 
                }




			 private void push(int newTop) {
			    if (stackSize == stack.length) {
			      stack = Arrays.copyOf(stack, stackSize * 2);
			    }
			    stack[stackSize++] = newTop;
			  }



		   private void writeDeferredName() throws IOException {
		
		    if (deferredName != null) {
		      //写入value 第一次的话 没有任何操作 只是修改状态为DANGLING_NAME
		      beforeName();
		      //将deferredName 变成"deferredName"写入
		      string(deferredName);
		      //写入之后 deferredName设置为null
		      deferredName = null;
		    }
		
		  }
		  
		  
		  
		    private void string(String value) throws IOException {
			    String[] replacements = htmlSafe ? HTML_SAFE_REPLACEMENT_CHARS : REPLACEMENT_CHARS;
			    out.write('\"');
			    int last = 0;
			    int length = value.length();
			    for (int i = 0; i < length; i++) {
			      char c = value.charAt(i);
			      String replacement;
			      if (c < 128) {
			        replacement = replacements[c];
			        if (replacement == null) {
			          continue;
			        }
			      } else if (c == '\u2028') {
			        replacement = "\\u2028";
			      } else if (c == '\u2029') {
			        replacement = "\\u2029";
			      } else {
			        continue;
			      }
			      if (last < i) {
			        out.write(value, last, i - last);
			      }
			      out.write(replacement);
			      last = i + 1;
			    }
			    if (last < length) {
			      out.write(value, last, length - last);
			    }
			    out.write('\"');
			  }
			  
			  
			    private JsonWriter close(int empty, int nonempty, char closeBracket)
				      throws IOException {
				    int context = peek();//NONEMPTY_OBJECT
				    if (context != nonempty && context != empty) {
				      throw new IllegalStateException("Nesting problem.");
				    }
				    //deferredName 不为空 表示没有写入 抛异常
				    if (deferredName != null) {
				      throw new IllegalStateException("Dangling name: " + deferredName);
				    }
				
				    stackSize--;
				    if (context == nonempty) {
				      newline();
				    }
				    out.write(closeBracket);
				    return this;
				  }
			  
			  
             } 
  • 方法说明

           nullValue():若此时序列化的对象是空,或者Json中key对应的value值是null,则调用该方法,它会判断deferredName(Java Object的的属性名)是否为空,若不为空则则写入属性名;然后通过beforeValue()判断是否需要写入key/value之间的分号“:”,最后通过out.write("null")写入null
           
    	       
           beginObject():在序列化Object类型的数据之前需要首先先调用该方法,它主要用于写入开始符号“(”,并将状态值从EMPTY_DOCUMENT变成EMPTY_OBJECT
           
           beginArray():在序列化Array类型的数据之前需要首先先调用该方法,它主要用于写入开始符号"[",并将状态值从EMPTY_DOCUMENT变成EMPTY_ARRAY
           
           endObject():在序列化Object类型的数据完成之后调用该方法,它主要用于写入结束符号"}"
           
           endArray():在序列化Array类型的数据完成之后调用该方法,它主要用于写入结束符号"]"
           		  
           peek():获取stackSize-1位置的状态值,也就是当前状态值
           
           newline():写入换行符
           
           push():修改当前状态,并将stackSize加1
           
           name():将Java Object的属性名赋值给deferredName
           
           string():将属性名/属性值添加双引号写入
           
           
           writeDeferredName():在value方法中被调用,主要写入属性名(deferredName),会判断属性名是否为空,若不为空则先调用beforeName()判断在name的前面 是否需要添加逗号“,” ,因为第一次会调用beginObject()/beginArray()方法时将状态变成EMPTY_OBJECT/EMPTY_ARRAY,此时不会写入逗号(","),但是在写入下一个key/value值时状态变成NONEMPTY_OBJECT/NONEMPTY_ARRAY将会写入逗号(","),逗号写入完成之后调用string()将属性名写入进去,写入完成之后调用replaceTop()将状态变成DANGLING_NAME
           
           
          beforeValue():写入value之前做的一些操作。该方法会根据对应的状态 进行一些操作 包含修改状态 换行 写入逗号或分号等
          
          
          
           value():写入key/value值,通过writeDeferredName()判断是否需要写入逗号(","),之后通过string()写入属性名的值;通过beforeValue()修改状态值,并根据状态是否需要写入逗号,分号等,最后通过string()写入属性对应的vlaue值
           
           
           close():写入结束符号
           
           open():    写入结束符号
    

总结一下:通过Gson的toJson()进行序列化操作,那么具体流程是怎么样的?到底是怎样一步步写入数据,将Java Array转换为Json字符串的

1.当创建Gson()对象时,在Gson的构造函数中初始化一个TypeAdapterFactory的集合,它包含了各种数据类型的解析器,若开发者自己定义了解析器,也会被添加到集合中,以便于序列化时调用getAdapter()获取对应类型的TypeAdapter
2.调用gson.toJson(object)方法,将数据传递进来,开始进行序列化操作
3.在toJson()方法中判断传入的数据是否为空

若传入的数据为空

          1.调用Streams.write(jsonElement, writer)方法进行写入,jsonElement为JsonNull; writer为JsonWriter
             
          2.然后在Streams.write()方法中调用 TypeAdapters.JSON_ELEMENT.write()进行写入,JSON_ELEMENT是一个TypeAdapter,用于对JsonElement类型的数据进行写入
              
          3.在JSON_ELEMENT中因为传入的数据是JsonNull,在TypeAdapter的write会调用nullValue(),最终通过Writer写入“null”字符串

若传入的数据不为空

          1.则通过TypeToken.get(typeOfSrc),创建一个TypeToken对象,这个TypeToken可以获取Java Object的类型
          
          2.之后以此为参数,遍历factories,创建可以解析Java Object对应数据的的TypeAdapter,若创建成功,就表示成功找到了对应的typeAdapter。对于不同数据类型有不同的typeAdapter解析器,Gson已经有了一些内置的typeAdapter(可以在TypeAdapters查看),同时也可以客户端自己定义对应类型的typeAdapter,在构建Gson的时候这些解析器会被添加到factories中,若定义的Java Object是自定义类型,也没有添加特定的typeAdapter,那么则采用通用的ReflectiveTypeAdapterFactory以反射的形式进行数据的处理
          
          3.找到对应的TypeAdapter后调用typeAdapter.write()方法,那么一般对于Java Array,若没有采用TypeAdapter注解注册对应的typeAdapter,那么就会使用CollectionTypeAdapterFactory进行处理,所以我们看看CollectionTypeAdapterFactory
          
          4.CollectionTypeAdapterFactory的构造函数中包含ConstructorConstructor(用于构建Java Object的实例对象) 
         
          5.CollectionTypeAdapterFactory实现了TypeAdapterFactory接口,重写了create(),在该方法中通过gson.getAdapter(TypeToken.get(elementType))获取元素的TypeAdapter,在TypeAdapter的write/read中被使用,针对集合中具体的元素类型采用对应的TypeAdapter进行序列化和反序列化
          
               
          6.在CollectionTypeAdapterFactory的typeAdapter的write方法中,首先会调用out.beginArray()写入json字符串的开始符号“[”,此时JsonWriter的stack状态数组中第一个位置的状态值由EMPTY_DOCUMENT变成NONEMPTY_DOCUMENT,第二个位置的状态值变成EMPTY_ARRAY
          
          7.然后遍历collection集合, 调用elementTypeAdapter.write(out, element)写入元素数据,若集合中是自定义的Java Object,那么elementTypeAdapter是ObjectTypeAdapter类型,也就是Object类型的,那么就会调用ObjectTypeAdapter的write方法,在ObjectTypeAdapter的write方法会根据gson.getAdapter(value.getClass())获取元素对应的typeAdapter,因为元素没有使用JsonAdapter注解添加自定义的TypeAdapter,所以当做一个Java Object,那么采用ReflectiveTypeAdapterFactory进行元素的json字符串的写入,在写入过程中,第一个元素的typeAdapter调用JsonWriter,beginObject(),因为此时的状态为EMPTY_ARRAY,不会在写入整个元素的数据之前写入逗号,但是当第二元素及后面的元素的typeAdapter调用JsonWriter,beginObject()时状态为NONEMPTY_OBJECT,会在写入整个元素的数据之前写入逗号,那么这样就将整个数组的元素都写入进去了,且每一个元素之间会有一个逗号
          
          8.遍历集合元素写入完成之后,调用endArray()写入json字符串的结束符号“]”,整个json数组字符串被写入完成
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值