'How to find the tag Value in the dynamic JSON-Object with Java 8

I have JSON-object which has a dynamic key inside it. I need to get a specific value mapped to this dynamic Key.

For example: value "10.00" will be returned for the key "value" and value REFUND_COMPLETED will be obtained as a result for the key "refundState"

Code:

public static void main(String[] args) {
        String json2 = "{\n"
                + "    \"refundStatusDetails\": {\n"
                + "        \"txn_f2a7802c-ef84-43c3-8615-5f706b995c23\": {\n"
                + "            \"refundTransactionId\": \"txn_f2a7802c-ef84-43c3-8615-5f706b995c23\",\n"
                + "            \"requestId\": \"refund-request-id-1\",\n"
                + "            \"refundState\": \"REFUND_COMPLETED\",\n"
                + "            \"amount\": {\n"
                + "                \"currency\": \"INR\",\n"
                + "                \"value\": \"10.00\"\n"
                + "            },\n"
                + "            \"refundRequestedTime\": 1513788119505,\n"
                + "}";

        System.out.println("JSON: " + json2);
        JsonParser p = new JsonParser();
        Map<String,String> res =check("refundState", p.parse(json2));
        System.out.println("JSON: " + res.get("refundState"));
    }

    private static Map<String,String> check(String key, JsonElement jsonElement) {
        Map<String,String> res = new HashMap<>();
        if (jsonElement.isJsonObject()) {
            Set<Map.Entry<String, JsonElement>> entrySet = jsonElement.getAsJsonObject().entrySet();
            entrySet.stream().forEach((x) ->{
                if (x.getKey().equals(key)) {
                    res.put(x.getKey(),x.getValue().toString());
                }
            });
        }
        return res;
        
    }


Solution 1:[1]

If you are interested to access any field in a JSON object structure then you can use a method like the following one that I used to access the fields that I needed from an JSON Array structure using "package org.json;"

public static final String COLLECTION_OBJECT = "collectionObject";
public static final String FIELD = "field";

private ArrayList<Object> getSearchFilterCriteriaAsString() {

    String jsonString = "{" +
                            "\n\"collectionObject\": " +
                                "[\n" +
                                    "{" +
                                        "\n\"field\": \"productId\"," +
                                        "\n\"value\": \"3\"," +
                                        "\n\"operator\": \"EQUALS\"\n" +
                                    "},\n" +
                                    "{" +
                                        "\n\"field\": \"productPrice\"," +
                                        "\n\"value\": \"15\"," +
                                        "\n\"operator\": \"MORE_THAN\"\n" +
                                    "},\n" +
                                    "{" +
                                        "\n\"field\": \"productQuantity\"," +
                                        "\n\"value\": \"25\"," +
                                        "\n\"operator\": \"LESS_THAN\"\n" +
                                    "}\n" +
                                "]\n" +
                            "}";
                            
        JSONObject jsonObject = new JSONObject(jsonString);

        JSONArray jsonArray = jsonObject.getJSONArray(COLLECTION_OBJECT);

        ArrayList<Object> filteredObjectsList = new ArrayList<>();

        if (jsonArray != null) {

            for (int i = 0; i < jsonArray.length(); i++) {

                JSONObject filteredObj = (JSONObject) jsonArray.get(i);

                filteredObjectsList.add(filteredObj.getString(FIELD));
            }
            
        }
        
        return filteredObjectsList;
    }

As long as you know your key values you can parse any JSON as deep you want, without to care about how big it is, how many attributes it has.

Solution 2:[2]

I have JSON Object which has a dynamic key inside the object I need a specific key value

The recursive method listed below is capable of fetching the value mapped to the provided key from a nested JSON-object.

The method return an optional result.

If provided JsonElement is not a JsonObject an empty optional will be returned.

Otherwise, if the given JSON-object contains the given key the corresponding value wrapped by an optional will be returned. Or if it's not the case the entry set obtained from an object will be processed with stream. And for every JSON-object in the stream method getValue() will be called recursively.

If the given key is present in one of the nested objects, the first encountered non-empty optional will be returned. Or empty optional if the key was not found.

private static Optional<JsonElement> getValue(String key, JsonElement jsonElement) {
    if (!jsonElement.isJsonObject()) {
        return Optional.empty();
    }

    JsonObject source = jsonElement.getAsJsonObject();

    return source.has(key) ? Optional.of(source.get(key)) :
            source.entrySet().stream()
                    .map(Map.Entry::getValue)
                    .filter(JsonElement::isJsonObject)
                    .map(element -> getValue(key, element))
                    .filter(Optional::isPresent)
                    .findFirst()
                    .orElse(Optional.empty());
}

main() - demo

public static void main(String[] args) {
    String json2 =
            """
                      {
                      "refundStatusDetails": {
                        "txn_f2a7802c-ef84-43c3-8615-5f706b995c23": {
                          "refundTransactionId": "txn_f2a7802c-ef84-43c3-8615-5f706b995c23",
                          "requestId": "refund-request-id-1",
                          "refundState": "REFUND_COMPLETED",
                          "amount": {
                            "currency": "INR",
                            "value": "10.00"
                          },
                          "refundRequestedTime": "1513788119505"
                        }
                      }
                    }""";

    JsonElement element = JsonParser.parseString(json2);
    System.out.println(getValue("refundState", element));
    System.out.println(getValue("value", element));
}

Output

Optional["REFUND_COMPLETED"]
Optional["10.00"]

Note:

  • If you are using Java 17 you can utilize text blocks by plasing the text between the triple quotation marks """ JSON """.
  • Constructor of the JsonParser is deprecated. Instead of instantiating this class, we have to use its static methods.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Vladmix6
Solution 2