pedrofsn
pedrofsn

Reputation: 327

How can I parse an associative array using Gson Converter in Retrofit?

I'm receiving a JSON response from a PHP server. In android, I need to write a java model (POJO) to use to parse the response in Retrofit (An Android library for http-requests).

JSON Structure:

{
  "calendar": {
    "2016-06-10": [
      {
        "time": "10h00m",
        "title": "PROVA P2",
        "description": "LP / RED / ED.FIS - 80 E 90",
        "color": "#990000"
      }
    ],
    "2016-06-11": [
      {
        "time": "10h00m",
        "title": "SIMULADO",
        "description": "LOREM PSIUM DOLOR LOREM",
        "color": "#009900"
      },
      {
        "time": "11h00m",
        "title": "CONSELHO DE CLASSE",
        "description": "LOREM PSIUM DOLOR",
        "color": "#009900"
      }
    ]
  },
  "error": false
}

This JSON is from PHP Server. How can I handle it using Retrofit?

Upvotes: 5

Views: 1254

Answers (3)

Clive Seebregts
Clive Seebregts

Reputation: 2024

To parse JSON with dynamic keys, you will need a Map in your POJO class.

Add the following POJO classes to your project:

  1. CalendarResponse.java

    public class CalendarResponse {
      @SerializedName("calendar")
      Map<String, List<Entry>> entries;
    
      @SerializedName("error")
      private boolean error;
    }
    
  2. Entry.java

    public class Entry {
      @SerializedName("time")
      private String time;
    
      @SerializedName("title")
      private String title;
    
      @SerializedName("description")
      private String description;
    
      @SerializedName("color")
      private String color;
    }
    
  3. Use the CalendarResponse class in your retrofit interface for your endpoint, see example below

    public interface CalendarService {
      @GET("<insert your own relative url>")
      Call<CalendarResponse> listCalendar();
    }
    
  4. Execute the call (synchronously) as follows:

    Call<CalendarResponse> call = calendarService.listCalendar();
    CalendarResponse result = call.execute().body();
    

If needed, here is an example to parse the JSON with GSON:

Gson gson = new GsonBuilder().create();
CalendarResponse b = gson.fromJson(json, CalendarResponse.class);

Upvotes: 6

Jaythaking
Jaythaking

Reputation: 2102

What I does when I don't want to create a POJO for a weird response from the server is keep it as a JSON in java and parse the string to create a JSON object. (Yes because sometimes we just can't control what the API guy is coding...)

As Cristan said, it would be strange to create a 2016-06-10 class. So, better handle it directly as a JSON object for that particular case. You can access any attribute using a JSON container and even store it in a database that way.

What you need to do if you choose that path:

private String sendAlert(String lat, String lon) throws IOException, JSONException {

    Call<ResponseBody> call = cougarServices.postAlert(lat, lon);
    ResponseBody response = call.execute().body();
    JSONObject json = (response != null ? new JSONObject(response.string()) : null);
    return handleJsonRequest(json);

}

Upvotes: 0

Cristan
Cristan

Reputation: 14085

Normally, you would create a POJO which is a representation of your JSON, but in this case, you would need a 2016-06-10 class and a 2016-06-11 class.

This isn't a solution. Therefore, change the JSON response to make the date a separate value:

{
  "calendar": [
    {
      "date": "2016-06-10",
      "entries": [
        {
          "time": "10h00m",
          "title": "PROVA P2",
          "description": "LP / RED / ED.FIS - 80 E 90",
          "color": "#990000"
        }
      ]
    }
  ]
}

Better yet, just make one dateTime value and make it a proper ISO 8601 timestamp while you're at it:

{
  "calendar": [
      {
        "time": "2016-06-10T08:00:00.000Z",
        "title": "PROVA P2",
        "description": "LP / RED / ED.FIS - 80 E 90",
        "color": "#990000"
      }
    ]
}

If you have no control over the server serving the JSON then you should use Retrofit to just get a String and do the Gson conversion yourself via gson.

Upvotes: 0

Related Questions