skip to Main Content

I have a JSON String and convert it to JSONObject.

I want to get specific data from the JSONObject, and every time the JSONObject changes its structure, sometimes it’s in an array inside the JSON and sometimes not.
example:
the first time the JSON arrives like this

{
  "id": "1",
  "Name": "Jack",
  "Value": {
    "data": [
      {"time": "2023", "age": "22"}
    ]
}}

the second time

{ 
  "age": "22",
  "time": "2023",
  "Value": {
    "data": [
      {"Name": "Jack", "id": "1" }
    ]
}}

if I want to get the name in the first JSON

jsonObject.getString("Name")

and for the second one, I would use

jsonObject.getJSONArray("data").getJSONObject(0).getString("Name")

is there a way I can get the value dynamically regardless of where the keys are?

3

Answers


  1. If your API come from an another team or an external provider, the first thing I would suggest to you, is to clearly define a contract. Otherwise, you can use the isNull(String key) method of JSONObject to check if the key exists or not.

    An example here:

    JSONObject jsonObject = new JSONObject(YOUR_JSON_STRING);
    String nameValue;
    
    if(jsonObject.isNull("Name")) {
        nameValue = jsonObject.getJSONObject("Value")
                    .getJSONArray("data")
                    .getJSONObject(0)
                    .getString("Name");
    } else {
        nameValue = jsonObject.getString("Name");
    }
    
    System.out.println(nameValue);
    
    Login or Signup to reply.
  2. If the JSON strings are always in a similar fashion then you can try a little parser method as provided below. It returns a Key/Value (String/Object) Map:

    public static java.util.Map<String, Object> mapJsonObject(String jsonString) {
        String json = jsonString
                .replaceAll("(?i)[\[\]\{\}"]|"?value"?:|"?data"?:|n?", "")
                .replaceAll("\s+", " ");
        String[] keyValueParts = json.split("\s*,\s*");
        java.util.Map<String, Object> map = new java.util.HashMap<>();
        for (String str : keyValueParts) {
            String[] pts = str.split("\s*:\s*");
            map.put(pts[0].trim(), pts[1]);
        }
        return map;
    }
    

    To use:

    String jsonString = "{n"
                + "  "id": "1",n"
                + "  "Name": "Jack",n"
                + "  "Value": {n"
                + "    "data": [n"
                + "      {"time": "2023", "age": "22"}n"
                + "    ]n"
                + "}}";
    
    java.util.Map<String, Object> map = mapJsonObject(jsonString);
    System.out.println(map);
    

    The console window will display:

    {id=1, time=2023, age=22 , Name=Jack}
    
    Login or Signup to reply.
  3. You may consider library Josson.

    https://github.com/octomix/josson

    Deserialization

    Josson josson1 = Josson.fromJsonString(
        "{" +
        "  "id": "1"," +
        "  "Name": "Jack"," +
        "  "Value": {" +
        "    "data": [" +
        "      {"time": "2023", "age": "22"}" +
        "    ]" +
        "  }" +
        "}");
    
    Josson josson2 = Josson.fromJsonString(
        "{ " +
        "  "age": "22"," +
        "  "time": "2023"," +
        "  "Value": {" +
        "    "data": [" +
        "      {"Name": "Jack", "id": "1" }" +
        "    ]" +
        "  }" +
        "}");
    

    Query

    *() is a multi-level wildcard search. It returns the first resolvable element.

    System.out.println(josson1.getString("coalesce(Name, *().Name)"));
    // Output: Jack
    
    System.out.println(josson2.getString("coalesce(Name, *().Name)"));
    // Output: ["Jack"]
    // It is because "Name" is inside array "data".
    
    System.out.println(josson1.getString("coalesce(Name, *().Name).first()"));
    // Output: Jack
    
    System.out.println(josson2.getString("coalesce(Name, *().Name).first()"));
    // Output: Jack
    // Added function first() to extract the value.
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search