在使用gson过程中,一般会将数据存在一个对象模型中,使用gson将模型转换成json字符串用于数据交互。

代码形如:

        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));

程序输出内容为:

list to json is : ["test1","test2"]

但是当转化对象是匿名类时:

        ArrayList<String> arrayList =  new ArrayList<String>() {{
add("对");
add("不对");
}};
Gson gson = new Gson();
System.out.println("isAnonymousClass list to json is : "+gson.toJson(arrayList));

程序输出内容为:

isAnonymousClass list to json is : null

同理,如果使用模型对象,模型的某个字段的实例对象为匿名类,这个字段序列化的结果也是null。

这里我们研究一下gson的实现来分析原因:

首先,通过gson.toJson方法的实现很容易招到com.google.gson.Gson#toJson(java.lang.Object, java.lang.reflect.Type, com.google.gson.stream.JsonWriter) 这个方法,实现如下:

  /**
* 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方法

 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实例,

这里我们关注的是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

05-11 20:43