Каков наилучший способ обработки ответов JSON API с помощью GSON?
Я работаю над проектом, который взаимодействует с API, используя JSON. Это моя первая попытка в JSON, и я был вдали от Java несколько лет, поэтому, пожалуйста, потерпите меня.
Вот идея того, как выглядят данные:
Строка 1:
[{
"apicall1":
[{
"thisField":"thisFieldData",
"thatField":"thatFieldData",
"anotherField":"anotherFieldData"
}]
}]
Строка 2:
[{
"apicall2":
[{
"thatField":"thatFieldData",
"someFieldsAreTheSame":"someFieldsAreTheSameData",
"otherFieldsAreNotTheSame":"otherFieldsAreNotTheSame"
}]
}]
Как вы можете видеть из моего примера данных, API возвращает строку JSON, содержащую используемый API. Массив внутри содержит данные. У API много общих полей данных, но они не связаны с этим.
РЕДАКТИРОВАТЬ: Есть десятки этих типов API, которые должны быть обработаны.
Я пытаюсь создать класс ответа, который принимает все строки JSON и возвращает объект, содержащий соответствующие данные.
Например:
Gson gson = new Gson(); //Custom TypeAdapter goes here if needed.
Response apicall2 = gson.fromJson(apicall2String, Response.class);
System.out.println(apicall2.thatField); //Prints thatFieldData
System.out.println(apicall2.someFieldsAreTheSame); //Prints someFieldsAreTheSameData
System.out.println(apicall2.otherFieldsAreNotTheSame); //Prints otherFieldsAreNotTheSameData
Это где я потерян. Вот что у меня так далеко. Я думаю, что мне нужно использовать TypeAdapter здесь, но я не смог понять, как применить это в моем случае.
public class Response { //Change to TypeAdapter possibly?
}
public class apicall1 {
String thisField;
String thatField;
String anotherField;
}
public class apicall2 {
String thatField;
String someFieldsAreTheSame;
String otherFieldsAreNotTheSame;
}
2 ответа
Вы можете использовать Gson's TypeToken
класс для десериализации JSON в объект. Ниже приведен пример:
JSON:
[{ "apicall1":
[{
"thisField":"thisFieldData",
"thatField":"thatFieldData",
"anotherField":"anotherFieldData"
}]
}]
Модель:
class Response{
private List<Result> apicall1;
class Result{
private String thisField;
private String thatField;
private String anotherField;
public String getThisField() {
return thisField;
}
public void setThisField(String thisField) {
this.thisField = thisField;
}
public String getThatField() {
return thatField;
}
public void setThatField(String thatField) {
this.thatField = thatField;
}
public String getAnotherField() {
return anotherField;
}
public void setAnotherField(String anotherField) {
this.anotherField = anotherField;
}
}
public List<Result> getApicall1() {
return apicall1;
}
public void setApicall1(List<Result> apicall1) {
this.apicall1 = apicall1;
}
}
Преобразователь:
public static void main(String[] args) {
String response = "[{ \"apicall1\": [{ \"thisField\":\"thisFieldData\", \"thatField\":\"thatFieldData\", \"anotherField\":\"anotherFieldData\" }]}]";
Gson gson = new Gson();
List<Response> responses = gson.fromJson(response, new TypeToken<List<Response>>(){}.getType());
System.out.println(responses.get(0).getApicall1().get(0).getThisField());
}
Я не знаю, хотите ли вы оба адаптера в одном классе. Может быть не лучший дизайн ООП.
Для этого вам нужно сделать что-то вроде этого:
public class DoublyTypeAdapter implements JsonDeserializer<ApiCallTypeParent>
{
Gson gson = new Gson();
@Override
public ApiCallTypeParent deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext)
throws JsonParseException {
JsonObject json = jsonElement.getAsJsonObject();
ApiCallTypeParent desrializeIntoMe;
// Detect which type to implement
if(apiTypeOne(type) {
desrializeIntoMe = new TypeOne();
} else {
desrializeIntoMe = new TypeTwo();
}
for (Map.Entry<String, JsonElement> entry : json.entrySet())
{
switch(entry.getKey()){
case "thisField":
desrializeIntoMe.setThisField(entry.getValue().getAsString());
break;
......
default: // We don't care
break;
}
}
return desrializeIntoMe ;
}
}