内容简介:Gson源码分析
如今使用 Json 数据格式通信几乎是再平常不过的事情,以至于都忘了去研究 Json 字符串与 Object 之间到底是怎样转换的,只记得简单的调用几个简单的 API。Gson 是 Java 语言的 Json 库,通常也是 Android 平台的首选方案,org.json(Android 内建 json 库) 相比更加底层,适合编写 toJson() 类函数或者对 Java 反射有限制的平台。深入 Gson 代码发现简单的 Json 解析也有如此多的可圈可点之处,Gson 的架构方案非常优美,结构清晰扩展性强,本文对此展开分析。
本文分析代码基于版本 3090a7ed2a 。文章篇幅有限希望读者下载相应代码以观全貌而不是仅仅限于本文列出的代码。
首先 Gson 对象提供了两种构建方法,一种是默认参数的 Constructor, new Gson()
,我们可以看到有数不清的配置参数,通过 new Gson()
我们可以快速得到一个开箱即用的默认 Gson 对象;同时为了满足自定义策略 Gson 使用 Builder 模式提供了另一种构建方法, 通过 GsonBuilder 可以调节 Gson 对象的细节参数,具体请阅读 GsonBuilder
,最终在 GsonBuilder#create
方法中通过包内权限的 Gson 默认构建函数得到 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, List<TypeAdapterFactory> typeAdapterFactories) { ... factories.add(new ReflectiveTypeAdapterFactory( constructorConstructor, fieldNamingStrategy, excluder, jsonAdapterFactory)); }
对于 LongSerializationPolicy,FieldNamingStrategy,ExclusionStrategies,SerializationExclusionStrategy, DeserializationExclusionStrategy 等不同方案使用了枚举,策略模式进行封装,如在系列化 Long 类型值时是用 long 还是 字符型策略:
public enum LongSerializationPolicy { DEFAULT() { @Override public JsonElement serialize(Long value){ return new JsonPrimitive(value); } }, STRING() { @Override public JsonElement serialize(Long value){ return new JsonPrimitive(String.valueOf(value)); } }; public abstract JsonElement serialize(Long value); }
Gson 对象中内建了解析不同 Java 类型的 TypeAdpater 分别处理不同类型的 Json 结构。然后 在 fromJson, toJson 方法中调用 Adapter 的 read, write 方法递归的解析出不通层次 json 值。同时允许用户在 GsonBuilder 中注册自定义的 Adpater 完成高级操作,这是 Gson 高扩展性的原因。
Gson 中重载了多种参数的 toJson,fromJson 函数,但最终落地到这两个函数上,然后将数据的系列化与反序列化逻辑移交到 Adapter 的 write 与 read 函数中。
public <T> T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException{ ... try { reader.peek(); isEmpty = false; TypeToken<T> typeToken = (TypeToken<T>) TypeToken.get(typeOfT); TypeAdapter<T> typeAdapter = getAdapter(typeToken); T object = typeAdapter.read(reader); return object; } catch (Exception e) { ... } } public void toJson(Object src, Type typeOfSrc, JsonWriter writer) throws JsonIOException{ TypeAdapter<?> adapter = getAdapter(TypeToken.get(typeOfSrc)); ... try { ((TypeAdapter<Object>) adapter).write(writer, src); } catch (Exception e) { ... } }
其中通过 getAdpater 函数获取到对应类型的 Adapter 对象,getAdapter 中做了很多优化。首先 typeTokenCache 是一个线程安全的 Map 对象,key 为对象的类型,value 为对应类型的 Adpater,如果在 typeTokenCache 中取到了对应的 Adapter 则返回不进行后续逻辑。如果 typeTokenCache 中没有对应 Adpater,同时考虑到线程安全,Gson 采用了 ThreadLocal 的方案解,从 calls 中取出当前线程的 Map 对象 threadCalls,如果 threadCalls 中能获取到相应类型的 Adpater 则返回,否则将当前线程的特定 Type 的 Adapter 设置为 FutureTypeAdapter,
接下来遍历所有已经注册的 AdapterFactory 的对象 factories,如果构造出对应类型的 Adpater 则把 FutureTypeAdapter 代理到相应的 Adapter 上并缓存近 typeTokenCache 提高下次访问性能。
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 cannot handle " + type); } finally { threadCalls.remove(type); if (requiresThreadLocalCleanup) { calls.remove(); } } }
通过 GsonBuilder 注册的 TypeAdater 在 GsonBuilder ,最终在 GsonBuilder#create 函数中做为 factories 参数传入了默认 Gson 构造函数中,而注册的这些 factories 会比内建的几个 Adapter 更早加入 factories 中,结合上面遍历 factories 的代码我们可以看到越早加入则先返回,也就是说在 GsonBuilder 中注册的相同类型 TypeAdatper 可以覆盖掉内建的 Adapter 从而实现自定义。
至此我们看到 Gson 框架实际上把对象的序列化与反序列工作分发到不同类型的 TypeAdapter 中,具体的工作由 Adapter 的 write 与 read 函数完成。Gson 本身提供了强大的流操作 工具 与丰富的 Adpater 类型以至于即使不自定义也有良好的开箱即用体验。深入 Adapter 相关代码我们发现在 factories 中除了注册了一堆 Primitive 类型的 Adapter 外,最后还有一个 ReflectiveTypeAdapterFactory,这个 ReflectiveTypeAdapterFactory 通过反射将 Java 对象属性与 Json 字符紧密连接。
首先在 ReflectiveTypeAdapterFactory#create 方法中可以看到,ReflectiveTypeAdapterFactory 适用于除原始类型外所有的 Java 对象类型。当然如果在 GsonBuilder 中注册了特定类型除外。
@Override public <T> TypeAdapter<T> create(Gson gson, final TypeToken<T> type){ Class<? super T> raw = type.getRawType(); if (!Object.class.isAssignableFrom(raw)) { return null; // it's a primitive! } ObjectConstructor<T> constructor = constructorConstructor.get(type); return new Adapter<T>(constructor, getBoundFields(gson, type, raw)); } ... Adapter(ObjectConstructor<T> constructor, Map<String, BoundField> boundFields) { this.constructor = constructor; this.boundFields = boundFields; }
在 ReflectiveTypeAdapterFactory 的构建函数中获取到了对象的构建函数句柄有能力直接构建新对象,并且 boundFields 存储了这个对象的所有属性。
private Map<String, BoundField> getBoundFields(Gson context, TypeToken<?> type, Class<?> raw){ Map<String, BoundField> result = new LinkedHashMap<String, BoundField>(); if (raw.isInterface()) { return result; } Type declaredType = type.getType(); while (raw != Object.class) { Field[] fields = raw.getDeclaredFields(); for (Field field : fields) { boolean serialize = excludeField(field, true); boolean deserialize = excludeField(field, false); if (!serialize && !deserialize) { continue; } field.setAccessible(true); Type fieldType = $Gson$Types.resolve(type.getType(), raw, field.getGenericType()); List<String> fieldNames = getFieldNames(field); BoundField previous = null; for (int i = 0, size = fieldNames.size(); i < size; ++i) { String name = fieldNames.get(i); if (i != 0) serialize = false; // only serialize the default name BoundField boundField = createBoundField(context, field, name, TypeToken.get(fieldType), serialize, deserialize); BoundField replaced = result.put(name, boundField); if (previous == null) previous = replaced; } if (previous != null) { throw new IllegalArgumentException(declaredType + " declares multiple JSON fields named " + previous.name); } } type = TypeToken.get($Gson$Types.resolve(type.getType(), raw, raw.getGenericSuperclass())); raw = type.getRawType(); } return result; }
getBoundFields 方法中获取到了一个类型的 BoundFields 并传给 ReflectiveTypeAdapter。我们可以在 getBoundFields 中处理了这个属性是否参与序列化,它的名字句柄信息并通过 createBoundField 方法结合在 Java 源码中的自定义注释等情况最终得到描述每个属性的 BoundField。createBoundField,BoundField 的结构如下:
private ReflectiveTypeAdapterFactory.BoundField createBoundField( final Gson context, final Field field, final String name, final TypeToken<?> fieldType, boolean serialize, boolean deserialize) { final boolean isPrimitive = Primitives.isPrimitive(fieldType.getRawType()); // special casing primitives here saves ~5% on Android... JsonAdapter annotation = field.getAnnotation(JsonAdapter.class); TypeAdapter<?> mapped = null; if (annotation != null) { mapped = jsonAdapterFactory.getTypeAdapter( constructorConstructor, context, fieldType, annotation); } final boolean jsonAdapterPresent = mapped != null; if (mapped == null) mapped = context.getAdapter(fieldType); final TypeAdapter<?> typeAdapter = mapped; return new ReflectiveTypeAdapterFactory.BoundField(name, serialize, deserialize) { @SuppressWarnings({"unchecked", "rawtypes"}) // the type adapter and field type always agree @Override void write(JsonWriter writer, Object value) throws IOException, IllegalAccessException { Object fieldValue = field.get(value); TypeAdapter t = jsonAdapterPresent ? typeAdapter : new TypeAdapterRuntimeTypeWrapper(context, typeAdapter, fieldType.getType()); t.write(writer, fieldValue); } @Override void read(JsonReader reader, Object value) throws IOException, IllegalAccessException { Object fieldValue = typeAdapter.read(reader); if (fieldValue != null || !isPrimitive) { field.set(value, fieldValue); } } @Override public boolean writeField(Object value) throws IOException, IllegalAccessException{ if (!serialized) return false; Object fieldValue = field.get(value); return fieldValue != value; // avoid recursion for example for Throwable.cause } }; } static abstract class BoundField{ final String name; final boolean serialized; final boolean deserialized; protected BoundField(String name, boolean serialized, boolean deserialized){ this.name = name; this.serialized = serialized; this.deserialized = deserialized; } abstract boolean writeField(Object value) throws IOException, IllegalAccessException; abstract void write(JsonWriter writer, Object value) throws IOException, IllegalAccessException; abstract void read(JsonReader reader, Object value) throws IOException, IllegalAccessException; }
BuildField 类通过递归的获取属性的 Adpater 并调用 read,write 方法描述了原来对象每个属性的反序列化与序列化怎么进行。至此我们不难猜出最后一步便是根据 BuildField 完成 ReflectiveTypeAdapter 的 read,write 方法便大功告成,ReflectiveTypeAdapter 的 read,write 方法如下:
@Override public T read(JsonReader in) throws IOException{ if (in.peek() == JsonToken.NULL) { in.nextNull(); return null; } T instance = constructor.construct(); try { in.beginObject(); while (in.hasNext()) { String name = in.nextName(); BoundField field = boundFields.get(name); if (field == null || !field.deserialized) { in.skipValue(); } else { field.read(in, instance); } } } catch (IllegalStateException e) { throw new JsonSyntaxException(e); } catch (IllegalAccessException e) { throw new AssertionError(e); } in.endObject(); return instance; } @Override public void write(JsonWriter out, T value) throws IOException{ if (value == null) { out.nullValue(); return; } out.beginObject(); try { for (BoundField boundField : boundFields.values()) { if (boundField.writeField(value)) { out.name(boundField.name); boundField.write(out, value); } } } catch (IllegalAccessException e) { throw new AssertionError(e); } out.endObject(); }
ReflectiveTypeAdapter 中对反序列化的处理遵循了以 Filed 属性为准的原则,如果在 Json 字符串中有值则赋予相应属性,如果没有则置空,由于预先遍历出了所有属性域所以解析过程复杂度为 O(N)。
由于 Adpater 递归的整体框架使得 Gson 具有很高的定制化能力,比如我们在 GsonBuilder 中注册 String.class 对应的 Adpater,而 GosnBuilder 中的 factories 比内建 Adapter 靠前实际上覆盖的内建的 String Adapter 的处理方案,因此我们对 Json 中的空字符串 “”, null 值等做统一化处理简化后期数据使用避免潜在问题。
本文重点研究 Gson 源码的构建原理,如果要了解 Gson 库的一些高级用法请参考官方文档: https://github.com/google/gson/blob/3090a7ed2af4d6d2e6bd3647d12839bb4ad404e8/UserGuide.md ,当然在了解原理的基础上看用法自然融会贯通。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 以太坊源码分析(36)ethdb源码分析
- [源码分析] kubelet源码分析(一)之 NewKubeletCommand
- libmodbus源码分析(3)从机(服务端)功能源码分析
- [源码分析] nfs-client-provisioner源码分析
- [源码分析] kubelet源码分析(三)之 Pod的创建
- Spring事务源码分析专题(一)JdbcTemplate使用及源码分析
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
马云现象的经济学分析:互联网经济的八个关键命题
胡晓鹏 / 上海社会科学院出版社 / 2016-11-1 / CNY 68.00
互联网经济的产生、发展与扩张,在冲击传统经济理论观点的同时,也彰显了自身理论体系的独特内核,并与那种立足于工业经济时代的经典理论发生显著分野。今天看来,“马云”们的成功是中国经济长期“重制造、轻服务,重产能、轻消费,重国有、轻民营”发展逻辑的结果。但互联网经济的发展却不应仅仅止步于商业技巧的翻新,还需要在理论上进行一番审慎的思考。对此,我们不禁要问:互联网经济驱动交易发生的机理是什么?用户基数和诚......一起来看看 《马云现象的经济学分析:互联网经济的八个关键命题》 这本书的介绍吧!