How to handle Dynamic JSON in Retrofit?
Late to the party, but you can use a converter.
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint("https://graph.facebook.com")
.setConverter(new DynamicJsonConverter()) // set your static class as converter here
.build();
api = restAdapter.create(FacebookApi.class);
Then you use a static class which implements retrofit's Converter:
static class DynamicJsonConverter implements Converter {
@Override public Object fromBody(TypedInput typedInput, Type type) throws ConversionException {
try {
InputStream in = typedInput.in(); // convert the typedInput to String
String string = fromStream(in);
in.close(); // we are responsible to close the InputStream after use
if (String.class.equals(type)) {
return string;
} else {
return new Gson().fromJson(string, type); // convert to the supplied type, typically Object, JsonObject or Map<String, Object>
}
} catch (Exception e) { // a lot may happen here, whatever happens
throw new ConversionException(e); // wrap it into ConversionException so retrofit can process it
}
}
@Override public TypedOutput toBody(Object object) { // not required
return null;
}
private static String fromStream(InputStream in) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
StringBuilder out = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
out.append(line);
out.append("\r\n");
}
return out.toString();
}
}
I have written this sample converter so it returns the Json response either as String, Object, JsonObject or Map< String, Object >. Obviously not all return types will work for every Json, and there is sure room for improvement. But it demonstrates how to use a Converter to convert almost any response to dynamic Json.
How to handle Retrofit JSON dynamically
If the Json is unknown that whether it will be JsonObject or JsonArray, then simply use JsonElement like below:
@SerializedName("data")
private JsonElement data;
Now to convert this JsonElement to your respective model as per your requirement you can use below code:
if(data instanceOf JsonObject){
YourModelForData object = YourDataComponentForObject(data);
// Do anything with Object
} else {
List<YourModelForData> array = YourDataComponentForArray(data);
// Do anything with array
}
public YourModelForData YourDataComponentForObject(JsonElement data) {
Type type = new TypeToken<YourModelForData>() {
}.getType();
YourModelForData item = new Gson().fromJson(data, type);
}
public List<YourModelForData> YourDataComponentForArray(JsonElement data) {
Type type = new TypeToken<List<YourModelForData>>() {
}.getType();
List<YourModelForData> items = new Gson().fromJson(data, type);
}
Happy Coding <{}>;
Retrofit Response with dynamic JSON array names
in that case you can use JSONObject for getting dynamic value just convert retrofit response to JSONObject for that you have to change response type of retrofit Call
Call<ResponseBody> call = exampleApi();
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Response<ResponseBody> response, Retrofit retrofit) {
String result = response.body().string();
JSONObject object = new JSONObject(result);
// can get any value from keys
// for example in your case
JSONArray array1 = object.getJSONObject('all').getJSONArray('loc1');
//similarly just change key to loc2 and so on
JSONArray array2 = object.getJSONObject('all').getJSONArray('loc2');
}
@Override
public void onFailure(Throwable t) {
}
});
Parse Dynamic Key Json String using Retrofit
Your resultInside
class is adding an extra object layer that does not exist in your JSON. Try moving the map to your Data
class results
field.
public class Data {
@SerializedName("results")
@Expose
private Map<String, Vitals> result;
//....
}
how to parse dynamic key response using retrofit
You need to change the response body type of Call<Data> call = apiService.getChampionData();
The response cannot be parsed to parsed one Data object, instead you should create a new response object like
public class DataResponse {
private Map<String, Data> data;
}
and call it Call<DataResponse> call = apiService.getChampionData()
;
Retrofit parse JSON dynamic keys
You could make your model POJO contain a Map<String, Champion>
to deserialize into, to deal with the dynamic keys.
Example:
public class ChampionData {
public Map<String, Champion> data;
public String type;
public String version;
}
public class Champion {
public int id;
public String title;
public String name;
public String key;
}
I'm not familiar with Retrofit besides that, but as someone in the comments said, the deserializing is done by Gson:
public ChampionData champions = new Gson().fromJson(json, ChampionData.class);
So to build on to the answer someone else posted, you can then do the following, assuming you've added the GsonConverterFactory
:
public interface API {
@GET("path/to/endpoint")
Call<ChampionData> getChampionData();
}
Related Topics
Check If Application Is Installed - Android
How to Check Grants Permissions At Run-Time
How to Display a List View in an Android Alert Dialog
Difference and Uses of Oncreate(), Oncreateview() and Onactivitycreated() in Fragments
What Does Layoutinflater in Android Do
How to Start Genymotion Device
How to Determine Android Physical Screen Height in Cm or Inches
How to Simulate a Touch Event in Android
Android Drawing Separator/Divider Line in Layout
How to Check If Alarmmanager Already Has an Alarm Set
How to Animate Recyclerview Items When They Appear
Android Writing Logs to Text File