Android Gson analiza el proceso de datos Json y cómo personalizar las reglas de análisis (centro)

Este artículo ha participado en el evento "Ceremonia de creación de recién llegados" para iniciar el camino hacia la creación de oro.

De acuerdo con el artículo anterior, necesitamos pasar por nuestro propio proceso para analizar la entrada. Necesitamos una GsonConverFactory propia, pero no queremos escribir otro código. Solo queremos cambiar los lugares clave. Definitivamente lo haremos piense en heredar directamente GsonConverFactory, pero desafortunadamente, esta clase es definitiva No se puede heredar, por lo que podemos copiar directamente esta clase para procesarla y personalizar nuestro propio adaptador paso a paso; nuestro objetivo es analizar y personalizar el tipo de objeto y el tipo de recopilación .

A través del código fuente se encuentra que la mayoría de las clases tienen la palabra clave final y no se pueden heredar, por lo que solo podemos copiar una copia, no hay manera.

Primero copie CollectionTypeAdapterFactory, luego copie lo que falta y luego copie ReflectiveTypeAdapterFactory también

Después de algunas copias, los archivos finales que deben copiarse son los siguientes:

  • Encontramos el método de lectura correspondiente a su WCollectionTypeAdapterFactory correspondiente y lo cambiamos de la siguiente manera

        @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();
        }

De la misma manera, el análisis y modificación del archivo de tipo de objeto de WReflectiveTypeAdapterFactory es el siguiente:

  @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;
        }

?, la parte central ha sido modificada. A continuación, debemos aplicar todos los cambios a retrofit2. Encontramos la clase WGsonConverFactory copiada. Esta clase es nuestra nueva clase de conversión. Necesitamos hacer algunas modificaciones dentro de ella. Dos WReflectiveTypeAdapterFactory y WCollectionTypeAdapterFactory son registrado en la instancia de Gson, reemplazando el analizador original con nuestro analizador, de la siguiente manera:

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

Finalmente, regístrelo para retrofit2 y reemplace el GsonConverFactory original de la siguiente manera:

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

Resultados de la prueba:

WCollectionTypeAdapterFactory se puede usar normalmente, pero la clase WReflectiveTypeAdapterFactory no se puede usar normalmente. Se estima que debido a que la clase JsonAdapterAnnotationTypeAdapterFactory está en Gson, pero la inicialización de WReflectiveTypeAdapterFactory necesita usarla, hay una secuencia de Gson.create()-->Gson initialization genera JsonAdapterAnnotationTypeAdapterFactory e inicializa ReflectiveTypeAdapterFactory -> Agregar a Gson, pero antes de que Gson se inicialice al registrar un analizador personalizado, no puede reemplazar ReflectiveTypeAdapterFactory en Gson

Supongo que te gusta

Origin juejin.im/post/7116811188008452132
Recomendado
Clasificación