在使用gson過程當中,通常會將數據存在一個對象模型中,使用gson將模型轉換成json字符串用於數據交互。html
代碼形如:java
ArrayList<String> list = new ArrayList<>(); list.add("test1"); list.add("test2"); Gson gson = new Gson(); System.out.println("list to json is : "+gson.toJson(list));
程序輸出內容爲:json
list to json is : ["test1","test2"]
可是當轉化對象是匿名類時:ide
ArrayList<String> arrayList = new ArrayList<String>() {{ add("對"); add("不對"); }}; Gson gson = new Gson(); System.out.println("isAnonymousClass list to json is : "+gson.toJson(arrayList));
程序輸出內容爲:ui
isAnonymousClass list to json is : null
同理,若是使用模型對象,模型的某個字段的實例對象爲匿名類,這個字段序列化的結果也是null。this
這裏咱們研究一下gson的實現來分析緣由:google
首先,經過gson.toJson方法的實現很容易招到com.google.gson.Gson#toJson(java.lang.Object, java.lang.reflect.Type, com.google.gson.stream.JsonWriter) 這個方法,實現以下:spa
/** * Writes the JSON representation of {@code src} of type {@code typeOfSrc} to * {@code writer}. * @throws JsonIOException if there was a problem writing to the writer */ @SuppressWarnings("unchecked") 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); } finally { writer.setLenient(oldLenient); writer.setHtmlSafe(oldHtmlSafe); writer.setSerializeNulls(oldSerializeNulls); } }
進入getAdapter方法code
public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) { TypeAdapter<?> cached = typeTokenCache.get(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 cannot handle " + type); } finally { threadCalls.remove(type); if (requiresThreadLocalCleanup) { calls.remove(); } } }
這裏,獲取adapter時,會從默認的工廠列表中逐個獲取工廠,基於傳入的類型獲取adapter實例,htm
這裏咱們關注的是com.google.gson.internal.Excluder這個工廠,
public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> type) { Class<?> rawType = type.getRawType(); final boolean skipSerialize = excludeClass(rawType, true); final boolean skipDeserialize = excludeClass(rawType, false); if (!skipSerialize && !skipDeserialize) { return null; } return new TypeAdapter<T>() { /** The delegate is lazily created because it may not be needed, and creating it may fail. */ private TypeAdapter<T> delegate; @Override public T read(JsonReader in) throws IOException { if (skipDeserialize) { in.skipValue(); return null; } return delegate().read(in); } @Override public void write(JsonWriter out, T value) throws IOException { if (skipSerialize) { out.nullValue(); return; } delegate().write(out, value); } private TypeAdapter<T> delegate() { TypeAdapter<T> d = delegate; return d != null ? d : (delegate = gson.getDelegateAdapter(Excluder.this, type)); } }; }
這裏
public boolean excludeClass(Class<?> clazz, boolean serialize) { if (version != Excluder.IGNORE_VERSIONS && !isValidVersion(clazz.getAnnotation(Since.class), clazz.getAnnotation(Until.class))) { return true; } if (!serializeInnerClasses && isInnerClass(clazz)) { return true; } if (isAnonymousOrLocal(clazz)) { return true; } List<ExclusionStrategy> list = serialize ? serializationStrategies : deserializationStrategies; for (ExclusionStrategy exclusionStrategy : list) { if (exclusionStrategy.shouldSkipClass(clazz)) { return true; } } return false; }
這裏調用了isAnonymousOrLocal這個方法(從方法名稱來看就是判斷是不是匿名類或本地類,其判斷是不是匿名類的邏輯是使用的java.lang.Class#isAnonymousClass方法,根據類名判斷),因爲skipSerialize和skipDeserialize 都由這個邏輯返回了true,最後create方法返回了Excluder工廠生成adapter對象.
由Excluder的註釋和返回的TypeAdapter對象都很容易看出,它的做用就是忽略該對象的j轉換,最終返回null