本文已参与「新人创作礼」活动,一起开启创作之路。
根据上篇文章,我们要把解析入口走我们自己的流程,我们需要一个自己的 GsonConverFactory 但是又不想写其他代码,只想改关键地方,我们肯定会想到直接继承GsonConverFactory 但是很遗憾,这个类带final 不能被继承,所以,我们可以直接把这个类复制一份处理,一步一步的自定义我们自己的适配器;我们的目标就是把Object类型和Collect类型解析自定义
通过源码发现,大部分类都是带final关键字,不能被继承,所以我们只能复制一份出来,没办法。
首先把 CollectionTypeAdapterFactory复制出来 然后缺啥复制啥出来然后ReflectiveTypeAdapterFactory也是如此
经过一番复制,最后需要复制出的文件如下:
- 我们找到其对应的 WCollectionTypeAdapterFactory对应的read方法,按照如下更改
@Override
public Collection<E> read(JsonReader in) throws IOException {
JsonToken peek = in.peek();
if (peek == JsonToken.NULL) {
in.nextNull();
return constructor.construct();//改动
} else if (peek != JsonToken.STRING) {//改动
Collection<E> collection = constructor.construct();
in.beginArray();
while (in.hasNext()) {
E instance = elementTypeAdapter.read(in);
collection.add(instance);
}
in.endArray();
return collection;
}
//必须要跳过不能解析的value,防止出现{arr:""}这种情况,指针停留在双引号之间,导致解析下一个name时出现空而爆粗
in.nextString();
return constructor.construct();
}
同理,对Object类型的文件WReflectiveTypeAdapterFactory解析修改如下:
@Override
public T read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
//如果是字符串,说明没有正确的数据 不能继续往下走,直接返回new的对象
if (in.peek() == JsonToken.STRING) {
in.nextString();//一定要调用这句话使jsonReader读取指针走到下一个字段中
return constructor.construct();
}
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;
}
?,核心部分已完成修改,接下来需要把所有的改动应用至retrofit2中,我们找到复制出来的WGsonConverFactory类,这个类作为我们新的转换类,其内部我们需要做点修改,把我们上面复制的两个WReflectiveTypeAdapterFactory和WCollectionTypeAdapterFactory注册到Gson实例中,把原来的解析器替换成我们的解析器,如下:
public class WGsonConverFactory extends Converter.Factory {
private static final String TAG = "WGSON";
//主要改动在这里
public static WGsonConverFactory create() {
GsonBuilder gsonBuilder = new GsonBuilder();
//通过反射获取各种属性 为其更换类型处理器
try {
Class builder = gsonBuilder.getClass();
Field f = builder.getDeclaredField("instanceCreators");
f.setAccessible(true);
Map<Type, InstanceCreator<?>> val = (Map<Type, InstanceCreator<?>>) f.get(gsonBuilder);//得到此属性的值
Field namingStra = builder.getDeclaredField("fieldNamingPolicy");
namingStra.setAccessible(true);
FieldNamingStrategy fieldNamingPolicy = (FieldNamingStrategy) namingStra.get(gsonBuilder);
Field filedExcluder = builder.getDeclaredField("excluder");
filedExcluder.setAccessible(true);
Excluder excluder = (Excluder) filedExcluder.get(gsonBuilder);
//这个类由于反射拿不到数据,所以也把他复制出来,直接new即可
JsonAdapterAnnotationTypeAdapterFactory jsonAdapterAnnotationTypeAdapterFactory = new JsonAdapterAnnotationTypeAdapterFactory(new ConstructorConstructor(val));
//注册数组的处理器
gsonBuilder.registerTypeAdapterFactory(new WCollectionTypeAdapterFactory(new ConstructorConstructor(val)));
gsonBuilder.registerTypeAdapterFactory(jsonAdapterAnnotationTypeAdapterFactory);
//注册Object;类型处理器
gsonBuilder.registerTypeAdapterFactory(new WReflectiveTypeAdapterFactory(new ConstructorConstructor(val), fieldNamingPolicy, excluder, jsonAdapterAnnotationTypeAdapterFactory));
} catch (NoSuchFieldException e) {
Log.e(TAG, "可能出现某个字段丢失导致多个类型适配器反射注册失败,这可能会影响之后的json数据解析 ", e);
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return create(gsonBuilder.create());
}
@SuppressWarnings("ConstantConditions") // Guarding public API nullability.
public static WGsonConverFactory create(Gson gson) {
if (gson == null) throw new NullPointerException("gson == null");
return new WGsonConverFactory(gson);
}
private final Gson gson;
private WGsonConverFactory(Gson gson) {
this.gson = gson;
}
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
Log.w("TYPE", "类型是 " + type.getTypeName());//
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new WGsonResponseBodyConverter<>(gson, adapter);
}
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new WGsonRequestBodyConverter<>(gson, adapter);
}
}
最后,将其注册到retrofit2,替换原来的GsonConverFactory, 使用方法如下:
this.host = GlobalStatusDataManager.getInstance().getHostPort();
File cacheDirectory = new File(context
.getCacheDir().getAbsolutePath(), "HttpCache");
builder = new OkHttpClient.Builder();
builder.addInterceptor(new HttpGlobalIntercepter());
builder.connectTimeout(TIMEOUT, TimeUnit.SECONDS);
builder.readTimeout(TIMEOUT, TimeUnit.SECONDS);
builder.writeTimeout(TIMEOUT, TimeUnit.SECONDS);
builder.cache(new Cache(cacheDirectory, 10 * 1024 * 1024));
userServiceAPI = new Retrofit.Builder()
.client(builder.build())
.baseUrl(this.host).addConverterFactory(WGsonConverFactory.create())//使用我们自己的转换器
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build()
.create(GsonTestAPI.class);
测试结果:
WCollectionTypeAdapterFactory 能正常使用,但是WReflectiveTypeAdapterFactory 这个类不能正常使用,估计由于JsonAdapterAnnotationTypeAdapterFactory这个类在Gson中,然而WReflectiveTypeAdapterFactory初始化需要用到他,存在先后顺序Gson.create()–>Gson初始化产生JsonAdapterAnnotationTypeAdapterFactory,初始化ReflectiveTypeAdapterFactory–>add到Gson中,但是注册自定义解析器时需要在Gson初始化前,所以无法替换Gson中ReflectiveTypeAdapterFactory