Dedicated Server
Showing posts with label parse json with unknown key. Show all posts
Showing posts with label parse json with unknown key. Show all posts

Parse json array with unkown key using Map in Android

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 :

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
Now generate the model classes as explained :

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



How to parse json with unknown key in android ?

We might have come across json responses which are having unknown key names. For example, a single response may output different key names when invoked different times. In this case we may not know the key value before hand so that we could parse it using the key name. In such case we should first get all the key values into a list of key names and then iterate over the key names one by one.

For example if a single endpoint(api request) gives two responses during two cases like below

case 1
{
"1":"abc",
"2","abc",
"3":"abc",
"4","abc"
}

case 2
{
"5":"abc",
"6","abc",
"7":"abc",
"8","abc"
}

You could make use of Iterator for looping through the list of key names.

Create a model class for saving the key and value pair like below

KeyValueModel.java

public class KeyValueModel {
    String keyName;
    String valueName;

    public KeyValueModel(String keyName, String valueName) {
        this.keyName = keyName;
        this.valueName = valueName;
    }

    public String getKeyName() {
        return keyName;
    }

    public String getValueName() {
        return valueName;
    }
}

Suppose you have a json response jsonObjectResponse(string). Then parse it like following


JSONObject jsonResponse = new JSONObject(jsonObjectResponse);
Iterator  iteratorObj = jsonResponse.keys();
ArrayList<KeyValueModel> responseList=new ArrayList<KeyValueModel>();
while (iteratorObj.hasNext())
     {
       String keyName = (String)iteratorObj.next();
       String valueName=jsonResponse.getString(keyName);
       KeyValueModel keyValueModel=new KeyValueModel(keyName,valueName);
       responseList.add(keyValueModel);
     }

Now you can access your response from responseList