How to Handle Dynamic Json in Retrofit

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



Leave a reply



Submit