Я хочу получить lastupdate
из data
более эффективным способом. Проблема в том, что то же имя data
используется как JsonObject или JsonArray. Позвольте мне объяснить.
Файл 'sample1. json' содержит один data
объект, а 'sample2. json' содержит несколько data
объектов.
Рабочий код ниже. Для простоты в 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);
}
}
}