Hi, this is yet another tutorial associated with json parsing in android. Let us see how can we parse a json array for which the key is not known beforehand. This means that the key names of the json array has to be identified and parsed dynamically.
You may take a look at one of my previous post regarding json parsing with unknown key, if you haven't already checked.
In this tutorial, we can make use of Map to parse the json array with dynamic key. We will be using retrofit library to perform the network calls.
First of all, add the following dependecies to your app level build.gradle file :
Let us try to parse a json response which will be like this sometimes
and it will be changing dynamically like this sometimes
Here you can see that the json array key names jan, jun are missing in second response. So we will have to dynamically parse these key names.
From the above response we can see that :
where String corresponds to "april" and List<MonthModel>> corresponds to the json array enclosed in [{}]
Example.java
Forecast.java
MonthModel.java
Now we can make the retrofit call as shown below
Create RequestInterface.java like this :
Now inside onResponse, you will have all the dynamic json array as Map inside resultMap
You may also check similar issue in StackOverflow
check this post on StackOverflow
You may take a look at one of my previous post regarding json parsing with unknown key, if you haven't already checked.
In this tutorial, we can make use of Map to parse the json array with dynamic key. We will be using retrofit library to perform the network calls.
First of all, add the following dependecies to your app level build.gradle file :
compile 'com.squareup.retrofit2:retrofit:2.0.0-beta4'
compile 'com.squareup.retrofit2:converter-gson:2.3.0'
Let us try to parse a json response which will be like this sometimes
{ "response": "success", "servicecode": "134", "forecast": { "month": { "jan": [ { "id": "1", "price": "12", "Product": "1086", "Qty": "14", "date": "2018-10-27 16:08:57" }, { "id": "2", "price": "19", "Product": "1746", "Qty": "45", "date": "2018-10-27 16:08:57" } ], "april": [ { "id": "3", "price": "89", "Product": "1986", "Qty": "15", "date": "2018-10-27 16:08:57" }, { "id": "1", "price": "12", "Product": "1086", "Qty": "145", "date": "2018-10-27 16:08:57" } ], "jun": [ { "id": "81", "price": "132", "Product": "17086", "Qty": "1445", "date": "2018-10-27 16:08:57" }, { "id": "11", "price": "132", "Product": "10786", "Qty": "1445", "date": "2018-10-27 16:08:57" } ] } }, "message": "Competitor Sales." }
and it will be changing dynamically like this sometimes
{ "response": "success", "servicecode": "134", "forecast": { "month": { "april": [ { "id": "3", "price": "89", "Product": "1986", "Qty": "15", "date": "2018-10-27 16:08:57" }, { "id": "1", "price": "12", "Product": "1086", "Qty": "145", "date": "2018-10-27 16:08:57" } ] } }, "message": "Competitor Sales." }
Here you can see that the json array key names jan, jun are missing in second response. So we will have to dynamically parse these key names.
From the above response we can see that :
- the entire response is enclosed in a json object({}), so we will create a model class(Example.java)
- we can see that there is one more json object inside the outer json object - forecast, so we will create another model class for it(Forcast.java)
- inside forecast, there is one more json object - month, but it contains some dynamically named json array. So we need to create a Map object that takes in a String and List<MonthModel>>. Please note that the Map object is used to parse the following pattern
"april": [ { "id": "3", "price": "89", "Product": "1986", "Qty": "15", "date": "2018-10-27 16:08:57" }
where String corresponds to "april" and List<MonthModel>> corresponds to the json array enclosed in [{}]
- So we need to create one more mode class MonthModel.java
Example.java
public class Example { @SerializedName("response") @Expose private String response; @SerializedName("servicecode") @Expose private String servicecode; @SerializedName("forecast") @Expose private Forecast forecast; @SerializedName("message") @Expose private String message; public String getResponse() { return response; } public void setResponse(String response) { this.response = response; } public String getServicecode() { return servicecode; } public void setServicecode(String servicecode) { this.servicecode = servicecode; } public Forecast getForecast() { return forecast; } public void setForecast(Forecast forecast) { this.forecast = forecast; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } }
Forecast.java
public class Forecast { @SerializedName("month") @Expose private Map<String, List<MonthModel>> result; public Map<String, List<MonthModel>> getResult() { return result; } public void setResult(Map<String, List<MonthModel>> result) { this.result = result; } }
MonthModel.java
public class MonthModel { @SerializedName("id") @Expose private String id; @SerializedName("price") @Expose private String price; @SerializedName("Product") @Expose private String product; @SerializedName("Qty") @Expose private String qty; @SerializedName("date") @Expose private String date; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getPrice() { return price; } public void setPrice(String price) { this.price = price; } public String getProduct() { return product; } public void setProduct(String product) { this.product = product; } public String getQty() { return qty; } public void setQty(String qty) { this.qty = qty; } public String getDate() { return date; } public void setDate(String date) { this.date = date; } }
Now we can make the retrofit call as shown below
private void getMonthData() { Gson gson = new GsonBuilder() .setLenient() .create(); Retrofit retrofit = new Retrofit.Builder() .addConverterFactory(GsonConverterFactory.create(gson)) .baseUrl("enter_base_url") .build(); RequestInterface requestInterface = retrofit.create(RequestInterface.class); Call<Example> call = requestInterface.getMonths(); call.enqueue(new Callback<Example>() { @Override public void onResponse(Call<Example> call, Response<Example> response) { Map<String, List<MonthModel>> resultMap=response.body().getForecast().getResult(); Toast.makeText(MainActivity.this, "Success", Toast.LENGTH_SHORT).show(); } @Override public void onFailure(Call<Example> call, Throwable t) { Toast.makeText(MainActivity.this, "Failure", Toast.LENGTH_SHORT).show(); } }); }
Create RequestInterface.java like this :
public interface RequestInterface { @GET("enter_url_endpoint") Call<Example> getMonths(); }
Now inside onResponse, you will have all the dynamic json array as Map inside resultMap
You may also check similar issue in StackOverflow

nice work
ReplyDeleteYou seem to be losing the month label (ie "April"). Am I right? Is there any way I can obtain that automatically?
ReplyDeleteHi, you can get the key and values like this.
Deletefor (Entry> data : data.getResult().entrySet()) {
Log.d("TAG", data.getKey()+":"); //this is for KEY name
for (int i = 0; i < data.getValue().size(); i++) {
Log.d("TAG", data.getValue().get(i)); //this is for VALUE of List
}
}
where you get Entry ? can u please make show complete code showing label and value , thank youu
Delete