Как разобрать JsonObject, JsonArray с таким же именем в Retrofit 2? - PullRequest
0 голосов
/ 15 марта 2020

Я хочу получить lastupdate из data более эффективным способом. Проблема в том, что то же имя data используется как JsonObject или JsonArray. Позвольте мне объяснить.

  1. Файл 'sample1. json' содержит один data объект, а 'sample2. json' содержит несколько data объектов.

  2. Рабочий код ниже. Для простоты в D_data, D_info, D_result я использую public переменные вместо «получателей». Ниже приведены 2 файла данных, 5 файлов c и MainActivity. java

Файл: sample1. json

{
  "info": {
    "lastupdate": "11:11"
  },
  "data": {
    "title": "AAA",
    "info": {
      "lastupdate": "12:01"
    }
  }
}

Файл: sample2. json

{
  "info": {
    "lastupdate": "22:22"
  },
  "data": [
    {
      "title": "BBB",
      "info": {
        "lastupdate": "12:02"
      }
    },
    {
      "title": "CCC",
      "info": {
        "lastupdate": "12:03"
      }
    },
    {
      "title": "DDD",
      "info": {
        "lastupdate": "12:04"
      }
    }
  ]
}

Sr c:

public class D_data {
  public String title;
  public D_info info;
}
public class D_info {
  public String lastupdate;
}
public class D_result {

  public D_info info;

//  public D_data data;    // for sample1.json
//  public D_data[] data;  // for sample2.json

  @SerializedName("data")
  public Object data;  // for both sample1.json and sample2.json

  public static class MyJsonDeserializer implements JsonDeserializer<D_result> {
    @Override
    public D_result deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {

      D_result result = new Gson().fromJson(json, D_result.class);

      JsonObject jsonObject = json.getAsJsonObject();
      if (jsonObject.has("data")) {
        JsonElement ele = jsonObject.get("data");
        if (ele != null && !ele.isJsonNull()) {
          if (ele.isJsonArray()) { result.data = ele.getAsJsonArray(); }
          else if (ele.isJsonObject()) { result.data = ele.getAsJsonObject(); }
        }
      }
      return result;
    }
  }
}
public class RetrofitClientInstance {

  private static Retrofit sRetrofit;
  private static final String BASE_URL = "http://192.168.0.xxx";  //fixme

  public static Retrofit getRetrofitInstance() {
    if (sRetrofit == null) {

      Gson gson = new GsonBuilder()
          .registerTypeAdapter(D_result.class, new D_result.MyJsonDeserializer())
          .create();

      sRetrofit = new retrofit2.Retrofit.Builder()
          .baseUrl(BASE_URL)
          .addConverterFactory(GsonConverterFactory.create(gson))
          .build();
    }
    return sRetrofit;
  }
}
public interface GetDataService {
  @GET("/dataset/{filename}")
  Call<D_result> getData(@Path("filename") String filename);
}

В MainActivity. java, добавьте:

  public void on_Get1_Click(View view) {
    vLoadData("sample1.json");  // contains one 'data' object
  }

  public void on_GetList_Click(View view) {
    vLoadData("sample2.json");  // contains multiple 'data' objects
  }

  private void vLoadData(String filename) {

    GetDataService service = RetrofitClientInstance
        .getRetrofitInstance().create(GetDataService.class);

    Call<D_result> call = service.getData(filename);
    Log.d(TAG, call.request().url().toString());

    call.enqueue(new Callback<D_result>() {
      @Override
      public void onResponse(Call<D_result> call, Response<D_result> response) {
        vParseResponse(response);
      }

      @Override
      public void onFailure(Call<D_result> call, Throwable t) { t.printStackTrace();

      }
    });
  }

  private void vParseResponse(Response<D_result> response) {

    D_result result = response.body();
    Log.d(TAG, result.info.lastupdate);  // expect '11:11' or '22:22' here

    try {
      JsonObject dataObj = (JsonObject) result.data;

      String title = String.format("%s", dataObj.get("title"));
      JsonObject infoObj = dataObj.getAsJsonObject("info");
      String lastupdate = String.format("%s", infoObj.get("lastupdate"));
      Log.d(TAG, title+" "+lastupdate);  // expect 'AAA 12:01'

    } catch (Exception e) { Log.e(TAG, "Error: not JsonObject"); }

    try {
      JsonArray jsonArray = (JsonArray) result.data;
      for (JsonElement element : jsonArray) {

        JsonObject dataObj = element.getAsJsonObject();

        String title = String.format("%s", dataObj.get("title"));
        JsonObject infoObj = dataObj.getAsJsonObject("info");
        String lastupdate = String.format("%s", infoObj.get("lastupdate"));
        Log.d(TAG, title+" "+lastupdate);  // expect 'BBB 12:02','CCC 12:03',and so on
      }
    } catch (Exception e) { Log.e(TAG, "Error: not JsonArray"); }
  }

В vParseResponse(), чтобы получить lastupdate значение '11: 11' или '22: 22 ', просто необходима эта строка ниже:

Log.d(TAG, result.info.lastupdate);

Однако, чтобы получить lastupdate из data (например, '12: 01', '12:02', ..), мне нужно пройти, используя JsonObject, .getAsJsonObject(), .get() несколько строк. Есть ли более эффективный способ сделать это? Например:

Log.d(TAG, data.info.lastupdate); // possible? if so, how?

В D_result, я использую public Object data;, а не public D_data data; или public D_data[] data;, чтобы я мог использовать JsonDeserializer , В результате я не могу получить значение, используя data.info.lastupdate. Как привести это Object обратно к D_data или D_data[]?

Произошел поиск вокруг, и выскочил TypeAdapter. Но я не мог понять, как его использовать.

Ссылки:

Дооснащение 2, одноименный другой тип данных JSON Разбор

Как использовать gson TypeAdapter в Retrofit 2?

Буду очень признателен, если кто-нибудь сможет предоставить советы / коды для (4), (5 ), (6)? Спасибо.

Решение

Sr c код обновлен с использованием JsonDeserializer и TypeAdapter. Теперь можно анализировать data в формате JsonObject или JsonArray.

public class D_result {

  public D_info info;

  private static final String TAG_DATA = "data";
  public D_data mD_data;
  public D_data[] mD_dataList;

  public void setD_data(D_data d_data) {
    mD_data = d_data;
  }

  public void setD_dataList(D_data[] d_dataList) {
    mD_dataList = d_dataList;
  }

  public static class MyJsonDeserializer implements JsonDeserializer<D_result> {
    @Override
    public D_result deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {

      D_result result = new Gson().fromJson(json, D_result.class);

      JsonObject jsonObject = json.getAsJsonObject();
      if (jsonObject.has(TAG_DATA)) {

        JsonElement ele = jsonObject.get(TAG_DATA);
        if (ele != null && !ele.isJsonNull()) {
          if (ele.isJsonArray()) {

            JsonArray jsonArray = jsonObject.getAsJsonArray(TAG_DATA);
            if (jsonArray != null && !jsonArray.isJsonNull()) {
              D_data[] values = new Gson().fromJson(jsonArray, new TypeToken<D_data[]>() {}.getType());
              result.setD_dataList(values);
            }
          }
          else if (ele.isJsonObject()) {

            JsonObject object = jsonObject.getAsJsonObject(TAG_DATA);
            if (object != null && !object.isJsonNull()) {
              D_data value = new Gson().fromJson(object, new TypeToken<D_data>() {}.getType());
              result.setD_data(value);
            }
          }
        }
      }
      return result;
    }
  }
}

private void vLoadData(String filename) {

    GetDataService service = RetrofitClientInstance
        .getRetrofitInstance().create(GetDataService.class);

    Call<D_result> call = service.getData(filename);
    Log.d(TAG, call.request().url().toString());

    call.enqueue(new Callback<D_result>() {
      @Override
      public void onResponse(Call<D_result> call, Response<D_result> response) {
        vParseResponse(response);
      }
      @Override
      public void onFailure(Call<D_result> call, Throwable t) { t.printStackTrace(); }
    });
  }

  private void vParseResponse(Response<D_result> response) {

    D_result result = response.body();
    Log.d(TAG, result.info.lastupdate);  // expect '11:11' or '22:22' here

    if (result.mD_data != null) {
      Log.d(TAG, result.mD_data.title + " " + result.mD_data.info.lastupdate);
    }
    else if (result.mD_dataList != null) {
      for (D_data data : result.mD_dataList) {
        Log.d(TAG, data.title + " " + data.info.lastupdate);
      }
    }
  }

...