Android Gson analyse le processus de données Json et comment personnaliser les règles d'analyse (milieu)

​Cet article a participé à l'événement "Newcomer Creation Ceremony" pour commencer la route vers la création d'or.

Selon l'article précédent, nous devons passer par notre propre processus d'analyse de l'entrée. Nous avons besoin de notre propre GsonConverFactory, mais nous ne voulons pas écrire d'autre code. Nous voulons juste changer les endroits clés. Nous allons certainement pensez à hériter directement de GsonConverFactory, mais malheureusement, cette classe est finale Elle ne peut pas être héritée, nous pouvons donc directement copier cette classe pour le traitement et personnaliser notre propre adaptateur étape par étape ; notre objectif est d'analyser et de personnaliser le type d'objet et le type de collecte .

Grâce au code source, on constate que la plupart des classes ont le mot-clé final et ne peuvent pas être héritées, nous ne pouvons donc copier qu'une copie, il n'y a aucun moyen.

Copiez d'abord le CollectionTypeAdapterFactory, puis copiez ce qui manque, puis copiez également le ReflectiveTypeAdapterFactory

Après quelques copies, les fichiers finaux à copier sont les suivants :

  • Nous trouvons la méthode de lecture correspondant à sa WCollectionTypeAdapterFactory correspondante et la modifions comme suit

        @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 même manière, l'analyse et la modification de WReflectiveTypeAdapterFactory du fichier de type d'objet est la suivante :

  @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 partie principale a été modifiée. Ensuite, nous devons appliquer toutes les modifications à retrofit2. Nous trouvons la classe WGsonConverFactory copiée. Cette classe est notre nouvelle classe de conversion. Nous devons y apporter quelques modifications. Deux WReflectiveTypeAdapterFactory et WCollectionTypeAdapterFactory sont enregistré dans l'instance Gson, en remplaçant l'analyseur d'origine par notre analyseur, comme suit :

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

Enfin, enregistrez-le pour rétrofit2 et remplacez le GsonConverFactory d'origine comme suit :

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

Résultats de test:

WCollectionTypeAdapterFactory peut être utilisé normalement, mais la classe WReflectiveTypeAdapterFactory ne peut pas être utilisée normalement. On estime que parce que la classe JsonAdapterAnnotationTypeAdapterFactory est dans Gson, mais que l'initialisation de WReflectiveTypeAdapterFactory doit l'utiliser, il existe une séquence Gson.create()--> Gson initialization génère JsonAdapterAnnotationTypeAdapterFactory et initialise ReflectiveTypeAdapterFactory --> Ajouter à Gson, mais avant que Gson ne soit initialisé lors de l'enregistrement d'un analyseur personnalisé, il ne peut pas remplacer ReflectiveTypeAdapterFactory dans Gson

Je suppose que tu aimes

Origine juejin.im/post/7116811188008452132
conseillé
Classement