Каков наилучший способ обработки ответов 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 ;
      }
}
Другие вопросы по тегам