59

I have a JSON result in the following format which JSON Lint shows this as a "Valid Response".

My question is: how do I access the content of "question_mark" since "141", "8911", etc are all dynamic values?

My sample code for accessing value of "product".

//Consider I have the first <code>JSONObject</code> of the "search_result" array and 
//I access it's "product" value as below.
String product = jsonObject.optString("product"); //where jsonObject is of type JSONObject.
//<code>product<code> now contains "abc".

JSON:

{
 "status": "OK",
 "search_result": [

            {
                "product": "abc",
                "id": "1132",
                "question_mark": {
                    "141": {
                        "count": "141",
                        "more_description": "this is abc",
                        "seq": "2"
                    },
                    "8911": {
                        "count": "8911",
                        "more_desc": "this is cup",
                        "seq": "1"
                    }
                },
                "name": "some name",
                "description": "This is some product"
            },
            {
                "product": "XYZ",
                "id": "1129",
                "question_mark": {
                    "379": {
                        "count": "379",
                        "more_desc": "this is xyz",
                        "seq": "5"
                    },
                    "845": {
                        "count": "845",
                        "more_desc": "this is table",
                        "seq": "6"
                    },
                    "12383": {
                        "count": "12383",
                        "more_desc": "Jumbo",
                        "seq": "4"
                    },
                    "257258": {
                        "count": "257258",
                        "more_desc": "large",
                        "seq": "1"
                    }
                },
                "name": "some other name",
                "description": "this is some other product"
            }
       ]
}

My question title "dynamic key" could be wrong but I don't know at this point what's a better name for this issue.

Any help would be greatly appreciated!

Zafer Celaloglu
  • 1,438
  • 1
  • 17
  • 28
Sagar Hatekar
  • 8,700
  • 14
  • 56
  • 72
  • I think you should be having the values of object inside question_mark before executing it. are you having? – Lalit Poptani Sep 05 '11 at 05:11
  • umm, no. I don't know how to access the values inside question mark. For that I'd have to do jsonObj.optJSONObject("141"); where 141 is dynamic and I wouldn't know it in advance. – Sagar Hatekar Sep 05 '11 at 05:15

5 Answers5

123

Use JSONObject keys() to get the key and then iterate each key to get to the dynamic value.

Roughly the code will look like:


// searchResult refers to the current element in the array "search_result" but whats searchResult?
JSONObject questionMark = searchResult.getJSONObject("question_mark");
Iterator keys = questionMark.keys();
    
while(keys.hasNext()) {
    // loop to get the dynamic key
    String currentDynamicKey = (String)keys.next();
        
    // get the value of the dynamic key
    JSONObject currentDynamicValue = questionMark.getJSONObject(currentDynamicKey);
        
        // do something here with the value...
}
Taslim Oseni
  • 6,086
  • 10
  • 44
  • 69
momo
  • 21,233
  • 8
  • 39
  • 38
  • +1 Awesome! That worked just fine! I saw your earlier response which suggested using keys() and I ended up printing the outer keys. Had it not been for your sample code, I'd ended up asking another question! :P Thanks again for the prompt response! High time SO supported multiple upvotes for a great answer! – Sagar Hatekar Sep 05 '11 at 05:31
  • 2
    Glad to be able to help :) Let me know if you have any question. We (the SO Community) are all here to help out – momo Sep 05 '11 at 05:34
  • I used your code once and here am again for another kudos momo – Illegal Argument Mar 25 '14 at 08:01
  • It's added a new knowledge of parsing dynamic key array to me, saved my time thanks – sujith s Oct 06 '15 at 06:46
  • Hi momo..Thanks for your answer. But I am not able to use the above solution as I am using retrofit and creating POJO classes through online tool generator which generates the classes for dynamic values. It is useless. Can you please suggest me how to achieve your best solution for my problem ? – Deepak Sharma Mar 15 '16 at 12:43
  • Hi momo..Thanks for your answer. – akshay bhange Apr 17 '16 at 08:21
  • This answer deserve more than an upvote but an upvote is all I can give. Thanks a billion! – X09 Jul 01 '16 at 02:30
14

Another possibility is to use Gson (Note, I use lombok here to generates getters/setters, toString, etc):

package so7304002;

import java.util.List;
import java.util.Map;

import lombok.AccessLevel;
import lombok.Data;
import lombok.NoArgsConstructor;

import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
import com.google.gson.reflect.TypeToken;

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class JsonDemo {
    @Data
    private static class MyMap {
        private int count;

        @SerializedName("more_description")
        private String moreDescription;

        private int seq;
    }

    @Data
    private static class Product {
        private String product;

        private int id;

        @SerializedName("question_mark")
        private Map<String, MyMap> questionMark;
    }

    @Data
    private static class MyObject {
        private String status;

        @SerializedName("search_result")
        private List<Product> searchResult;
    }

    private static final String INPUT = ""; // your JSON

    public static void main(final String[] arg) {
        final MyObject fromJson = new Gson().fromJson(INPUT, 
            new TypeToken<MyObject>(){}.getType());
        final List<Product> searchResult = fromJson.getSearchResult();
        for (final Product p : searchResult) {
            System.out.println("product: " + p.getProduct() 
                + "\n" + p.getQuestionMark()+ "\n");
        }
    }
}

Output:

product: abc
{141=JsonDemo.MyMap(count=141, moreDescription=this is abc, seq=2), 
 8911=JsonDemo.MyMap(count=8911, moreDescription=null, seq=1)}

product: XYZ
{379=JsonDemo.MyMap(count=379, moreDescription=null, seq=5), 
 845=JsonDemo.MyMap(count=845, moreDescription=null, seq=6), 
 12383=JsonDemo.MyMap(count=12383, moreDescription=null, seq=4), 
 257258=JsonDemo.MyMap(count=257258, moreDescription=null, seq=1)}
  • Thanks for that helpful info and tutorial on GSON, RC. +1 for the extra efforts on creating a complete code example - it will be helpful to others out here as well. – Sagar Hatekar Sep 05 '11 at 05:46
  • how do you call that from retrofit response, and new Gson().fromJson is not working for me – hossam scott Oct 28 '18 at 16:25
1

An example of using Google Gson

JSON data from the question:

{
    "status": "OK",
    "search_result": [
        {
            "product": "abc",
            "id": "1132",
            "question_mark": {
                "141": {
                    "count": "141",
                    "more_description": "this is abc",
                    "seq": "2"
                },
                "8911": {
                    "count": "8911",
                    "more_desc": "this is cup",
                    "seq": "1"
                }
            },
            "name": "some name",
            "description": "This is some product"
        },
        {
            "product": "XYZ",
            "id": "1129",
            "question_mark": {
                "379": {
                    "count": "379",
                    "more_desc": "this is xyz",
                    "seq": "5"
                },
                "845": {
                    "count": "845",
                    "more_desc": "this is table",
                    "seq": "6"
                },
                "12383": {
                    "count": "12383",
                    "more_desc": "Jumbo",
                    "seq": "4"
                },
                "257258": {
                    "count": "257258",
                    "more_desc": "large",
                    "seq": "1"
                }
            },
            "name": "some other name",
            "description": "this is some other product"
        }
    ]
}

Example code:

import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;

public class GsonExercise {
    public static void main(String[] args) {
        String jsonString = "{\"status\":\"OK\",\"search_result\":[{\"product\":\"abc\",\"id\":\"1132\",\"question_mark\":{\"141\":{\"count\":\"141\",\"more_description\":\"this is abc\",\"seq\":\"2\"},\"8911\":{\"count\":\"8911\",\"more_desc\":\"this is cup\",\"seq\":\"1\"}},\"name\":\"some name\",\"description\":\"This is some product\"},{\"product\":\"XYZ\",\"id\":\"1129\",\"question_mark\":{\"379\":{\"count\":\"379\",\"more_desc\":\"this is xyz\",\"seq\":\"5\"},\"845\":{\"count\":\"845\",\"more_desc\":\"this is table\",\"seq\":\"6\"},\"12383\":{\"count\":\"12383\",\"more_desc\":\"Jumbo\",\"seq\":\"4\"},\"257258\":{\"count\":\"257258\",\"more_desc\":\"large\",\"seq\":\"1\"}},\"name\":\"some other name\",\"description\":\"this is some other product\"}]}";
        JsonObject jobj = new Gson().fromJson(jsonString, JsonObject.class);
        JsonArray ja = jobj.get("search_result").getAsJsonArray();
        ja.forEach(el -> {
            System.out.println("product: " + el.getAsJsonObject().get("product").getAsString());
            JsonObject jo = el.getAsJsonObject().get("question_mark").getAsJsonObject();            
            jo.entrySet().stream().forEach(qm -> {
                String key = qm.getKey();
                JsonElement je = qm.getValue();
                System.out.println("key: " + key);
                JsonObject o = je.getAsJsonObject();
                o.entrySet().stream().forEach(prop -> {
                    System.out.println("\tname: " + prop.getKey() + " (value: " + prop.getValue().getAsString() + ")");
                });
            });
            System.out.println("");
        });
    } 
}

Output:

product: abc
key: 141
    name: count (value: 141)
    name: more_description (value: this is abc)
    name: seq (value: 2)
key: 8911
    name: count (value: 8911)
    name: more_desc (value: this is cup)
    name: seq (value: 1)

product: XYZ
key: 379
    name: count (value: 379)
    name: more_desc (value: this is xyz)
    name: seq (value: 5)
key: 845
    name: count (value: 845)
    name: more_desc (value: this is table)
    name: seq (value: 6)
key: 12383
    name: count (value: 12383)
    name: more_desc (value: Jumbo)
    name: seq (value: 4)
key: 257258
    name: count (value: 257258)
    name: more_desc (value: large)
    name: seq (value: 1)
Yuci
  • 27,235
  • 10
  • 114
  • 113
  • All of the above answers are working if the response has array and jsonobjects inside it, if the response is not json array, but same kind of response which has been posted in this thread, how to get the value inside question mark, similar question is posted here, please guide. https://stackoverflow.com/questions/63639243/fetch-the-jsonobject-value-to-a-variable-which-is-inside-the-dynamically-generat – la1 Aug 29 '20 at 09:38
0

The same thing can also be done using GSON, but instead of using GSON converter adapter to convert into to POJO. we will parse it manually. which gives us flexibility in case of dynamic JSON data.
let's say the JSON format is like below in my case.

{
  "dateWiseContent": {
    "02-04-2017": [
      {
        "locality": " Cross Madian Cross Rd No 4"
      }
    ],
    "04-04-2017": [
      {
        "locality": "Dsilva Wadi"
      },
      {
        "locality": " Cross Madian Cross Rd No 4",
        "appointments": []
      }
    ]
  }
}

in this case the dateWiseContent has dynamic object keys so we will parse this json string using JsonParser class.

  //parsing string response to json object
 JsonObject jsonObject = (JsonObject) new JsonParser().parse(resource);
  //getting root object
 JsonObject dateWiseContent = jsonObject.get("dateWiseContent").getAsJsonObject();

get the dynamic keys using Map.Entry<String, JsonElement> as given below

  // your code goes here
         for (Map.Entry<String, JsonElement> entry : dateWiseContent.entrySet()) {

           //this gets the dynamic keys
            String  dateKey = entry.getKey();

            //you can get any thing now json element,array,object according to json.

            JsonArray jsonArrayDates = entry.getValue().getAsJsonArray();
            int appointmentsSize = jsonArrayDates.size();

             for (int count = 0; count < appointmentsSize; count++) {

                   JsonObject objectData = jsonArrayDates.get(count).getAsJsonObject();
                   String locality = objectData.get("locality").getAsString();


             }
        }

similarly any level of dynamic json can be parsed using Map.Entry<String,JsonElement>

vikas kumar
  • 10,447
  • 2
  • 46
  • 52
0

You can use this logic. use org.json library

<dependency>
    <groupId>org.json</groupId>
    <artifactId>json</artifactId>
    <version>20211205</version>
</dependency>


public void parseJson(JSONObject jo, String key) {
Iterator<?> keyIterator;
String key1;
if (jo.has(key)) {
    System.out.println(jo.get(key));
} else {
    keyIterator = jo.keys();
    while (keyIterator.hasNext()) {
    key1 = (String) keyIterator.next();
    if (jo.get(key1) instanceof JSONObject) {
        if (!jo.has(key))
        parseJson(jo.getJSONObject(key1), key);
    } else if (jo.get(key1) instanceof JSONArray) {
        JSONArray jsonarray = jo.getJSONArray(key1);
        Iterator<?> itr = jsonarray.iterator();
        while (itr.hasNext()) {
        String arrayString = itr.next().toString();
        JSONObject jo1 = new JSONObject(arrayString);
        if (!jo1.has(key)) {
            parseJson(jo1, key);
        }
        }

    }
    }
}
}
Aakash Singh
  • 47
  • 1
  • 13
  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Feb 11 '22 at 09:38