使用翻新2来获取和获取未知数据集

时间:2018-10-16 06:54:30

标签: java android serialization mobile retrofit2

Retrofit是一个很棒的库,易于使用和维护,但是我的情况有所不同,众所周知,我们应该应用创建改造api的阶段并做出相应的响应,

改造实例:

retrofit = new Retrofit.Builder()
                .baseUrl(url)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(new ErrorCallAdapter.MyCallAdapterFactory())
                .client(httpClient)
                .build();
        return retrofit;

API接口:

 @GET("api/getTheResults")
 ErrorCallAdapter.MyCall<GeneralResponse<SomeEntity> getGenericMethod();

ErrorCallAdapter的一部分:

@Override
        public void enqueue(final MyCallback<Object> callback) {
            call.enqueue(new Callback<GeneralResponse<T>>() {
                @Override
                public void onResponse(final Call<GeneralResponse<T>> call, final Response<GeneralResponse<T>> response) {
                    final int code = response.code();
                    mainHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            if (response.isSuccessful()) {
                                if (response.body().getStatus() == 1) {
                                    callback.onResult(response.body().getResponse());
                                } else
                                    callback.onError(response.body().getMError());
                            } else
                                callback.onError(new MError(code,
                                        response.message() != null ? response.message() : "onResponse error"));
                        }
                    });
                }

                @Override
                public void onFailure(Call<GeneralResponse<T>> call, Throwable t) {
                    if (t != null)
                        callback.onError(new MError(501,
                                t.getMessage() != null ? t.getMessage() : "unexpected error"));
                    else
                        callback.onError(new MError(501,
                                "unexpected error"));
                }
            });

        }

获取数据的一部分:

public void loadUserSetupData() {
        ErrorCallAdapter.MyCall<GeneralResponse<Data>, Data> DataCall = apiManager.getData();
        setupDataMyCall.enqueue(new ErrorHandlingCallAdapter.MyCallback<Data>() {
            @Override
            public void onResult(Data data) {
                endProgressDialog();

                apiResult.onSuccess(data);
            }

            @Override
            public void onError(MError mError) {
                endProgressDialog();
                apiResult.onError(mError.getErrorMessage(mContext));
            }
        });
    }

我尝试获取的数据为JSON格式,

{
    "Status": 1,
    "Error": null,
    "ResponseList": [
        {
            "ErCode": 0,
            "Masseg": null,
            "DType": "OnceData",
            "Contents": {
                "VList": [{
                    "name":"name"
                    "name":"name"
                    "name":"name"
                  }],
                "WList": [{
                    "name":"name"
                    "name":"name"
                    "name":"name"
                  }, {
                    "name":"name"
                    "name":"name"
                    "name":"name"
                  }],
                "UList": [{
                    "name":"name"
                    "dd":"ddd" "DobledataType"
                    "object":"name"  "object data type"
                  }, {
                    "name":"name"
                    "int":"1"
                    "code":"15.00" "float data type
                  }],

            }
        }
    ]
}

“上面,我将“名称”称为实体对象(UList,VList和WList中的每个都是仅用于说明的对象)。

我的问题是:如何使改装适用于任何类型的数据,无论哪种类型它都会获取对象,这意味着我不知道“目录”列表是否具有特定类型的对象,我想要使其工作在我不知道对象的情况下可以接收任何类型的任何类型的情况下,我们可以指定味精DType(以前知道DType = data例如将执行某些操作),但是我们不知道是响应对象的类型(字符串,对象,整数或仅一个字符串的数组列表) 我们如何在Android改装中做到这一点?

1 个答案:

答案 0 :(得分:2)

如果您根本不知道“ Contents”字段的内容是什么,则可以将其直接设置为模型中的JSONObject,但是每次您要检索某些内容时都必须做一些工作在内容字段中。

但是,如果您知道它可以有什么类型,例如,您确定它可以是String数组,String或int类型,则可以使用自定义GSON deserializer

首先,您必须更改Model / Pojo以处理每种类型,例如:

abstract class Model {
    // put here all the fields you know the type is stable
}

// for when content is a list
public class ListModel extends Model {
    @SerializedName("Contents")
    List<String> content;
}

// for when content is a String
public class StringModel extends Model {
    @SerializedName("Contents")
    String content;
}

// add every other derived class you need for the other types that the content field can have

现在您可以创建一个反序列化器,它将返回正确的Model对象:

public class ModelDeserializer implements JsonDeserializer<Model> {
    @Override
    public Model deserialize(JsonElement json, Type typeOfT, 
                             JsonDeserializationContext context) 
                             throws JsonParseException {
        JsonObject jsonObject = json.getAsJsonObject();

        // get the "contents" field
        JsonElement contents = jsonObject.get("Contents");
        if (contents != null) {
            if (contents.isJsonArray()) { // if this is a list, parse as ListModel
                return context.deserialize(jsonObject, 
                    ListModel.class);
            }
            if (contents.isJsonPrimitive()) { // json primitives are number, string, bool, character
                if (contents.getAsJsonPrimitive().isString() {
                    return context.deserialize(jsonObject, StringModel.class);
                }
            }
            // do the same for every other type you might have
        }
        return null;
    }
}

最后,您必须告诉Retrofit和Gson使用该反序列化器:

Gson gson = new GsonBuilder()
         .registerTypeAdapter(Model.class, new ModelDeserializer())
         .create();

// just add the new gson object to your converterfactory
retrofit = new Retrofit.Builder()
            .baseUrl(url)
            .addConverterFactory(GsonConverterFactory.create(gson))
            .addCallAdapterFactory(new ErrorCallAdapter.MyCallAdapterFactory())
            .client(httpClient)
            .build();
    return retrofit;

它应该可以工作。