5

I have a very complex json structure. It contains many array elements and those array elements contains other array elements and so on.. Please see below json tree structure.

Json Tree Structure-1 :

enter image description here

Json Tree Structure-2 :

enter image description here

As highlighted above in yellow, I want to update the value of "rdKey" field. I wrote below code and it is perfectly working fine :

String json = "escaped string (as it's a big string, I can't put it here)";
JSONObject jsonObj = new JSONObject(json);

    if (jsonObj.has("responseMap")) {
        JSONObject responseMap = jsonObj.getJSONObject("responseMap");
        if (responseMap.has("ValueJson")) {
            JSONObject valueJson = responseMap.getJSONObject("ValueJson");
            if (valueJson.has("ticketBean_CM")) {
                JSONObject ticketBean_CM = valueJson.getJSONObject("ticketBean_CM");
                if (ticketBean_CM.has("addByGamma")) {
                    String addByGamma = ticketBean_CM.getString("addByGamma");
                    System.out.println(addByGamma);

                    if (addByGamma.equals("VCE")) {
                        if (responseMap.has("ScreenJson")) {
                            JSONObject screenJson = responseMap.getJSONObject("ScreenJson");
                            if (screenJson.has("sections")) {
                                JSONArray sectionArray1 = screenJson.getJSONArray("sections");
                                if (sectionArray1.length() > 0) {
                                    JSONObject section0 = sectionArray1.getJSONObject(0);
                                    if (section0.has("sections")) {
                                        JSONArray sectionArray2 = section0.getJSONArray("sections");
                                        if (sectionArray2.length() > 3) {
                                            JSONObject section6 = sectionArray2.getJSONObject(3);
                                            if (section6.has("sections")) {
                                                JSONArray sectionArray3 = section6.getJSONArray("sections");
                                                if (sectionArray3.length() > 1) {
                                                    JSONObject section8 = sectionArray3.getJSONObject(1);
                                                    if (section8.has("elements")) {
                                                        JSONArray elementsArray1 = section8
                                                                .getJSONArray("elements");
                                                        if (elementsArray1.length() > 0) {
                                                            JSONObject elements1 = elementsArray1.getJSONObject(0);
                                                            if (elements1.has("elements")) {
                                                                JSONArray elementsArray2 = elements1
                                                                        .getJSONArray("elements");
                                                                if (elementsArray2.length() > 4) {
                                                                    JSONObject elements2 = elementsArray2
                                                                            .getJSONObject(4);
                                                                    if (elements2.has("rdKey")) {
                                                                        System.out.println(
                                                                                elements2.getString("rdKey"));
                                                                        elements2.put("rdKey",
                                                                                "CircuitID(FullPartial)");
                                                                        System.out.println(
                                                                                elements2.getString("rdKey"));
                                                                        System.out.println(jsonObj.toString());
                                                                    }
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }

I want you guys to help me if there is any better solution for this. Can I do it without traversing the entire json object (till I find the concerned field) ? This solution will not work if json tree structure gets changes, it needs to be static as a success scenario of this code.

Please suggest better solution.

Punit
  • 324
  • 1
  • 4
  • 17
  • you can use `for loop` for ["responseMap", "ValueJson", "ticketBean_CM" , ..., 4 ] as your coding style is almost same – artgb Oct 04 '17 at 15:57
  • I'm not getting through it, could you please help. – Punit Oct 05 '17 at 07:33
  • It seems there are a lot of conditions inside your structure (like the positions in the arrays, and some columns names). Is it a specific constraint, like you won't need something like that after or do you need to go through these array often ? For the latter, I would suggest creating Java bean representing your object for easier access. Else, you can create your own tiny API to not repeat the "if lenght elements sections etc.". – Asoub Oct 16 '17 at 07:15
  • @Asoub : I need to go through these array much often i.e. in each and every call to my API I need to change the value of "rdKey".could you please enlighten to create a tiny API for not repeating it. – Punit Oct 16 '17 at 07:39
  • Sorry I wasn't clear, I meant "often" in terms of code: do you have a lot of code that goes through array to get/update specfic data like the one you posted above or is it the only place in your code you this ? I'll elaborate in an anwser – Asoub Oct 16 '17 at 09:10
  • No, it's the only instance of code in my entire application which I shared. There is no other place where I'm doing such an operation. – Punit Oct 16 '17 at 09:50

2 Answers2

2

If you want to escape traversing of JSON then you can use JSONPointer, available in same org.json library. E.g.:

String query = <json_pointer_query to element array>
JSONPointer pointer = new JSONPointer(query);
JSONObject elementsArrayJSON = (JSONObject) pointer.queryFrom(jsonObj);
elementsArrayJSON.put("rdKey","CircuitID(FullPartial)");

JSON Pointer query language can be referred in:

https://www.rfc-editor.org/rfc/rfc6901

Note: JSON Pointer is pretty basic, it doesn't support wild card. So you need to be sure about element names, otherwise it would throw exception.

Community
  • 1
  • 1
Sachin Gupta
  • 7,805
  • 4
  • 30
  • 45
  • It seems that you have modified the json string for it to be accepted by JSONPointer, but I can't alter/modify the input json, it is the which I get from another process. In your String query. – Punit Oct 11 '17 at 07:20
  • It is just an example of Query string, you can modify it accordingly – Sachin Gupta Oct 11 '17 at 07:40
1

If you're flexible on what library to use, maybe the JsonPath will be useful for you.

You can update all "elements" with "rdKey" using the following code:

JsonPath.parse(json).set("$..elements[?(@.rdKey)].rdKey", "CircuitID(FullPartial)").json()
sjabra
  • 21
  • 3
  • I need to update only single instance of "rdKey" not all. – Punit Oct 05 '17 at 07:31
  • The proposal of Punit is the shortest if you don't need the json transformed in objects. Else you can try with ObjectMapper from [Jackson][1] – code4fun Oct 10 '17 at 09:59
  • Sorry the previous comment is incomplete: The proposal of Punit is the shortest if you don't need the json transformed in objects. Probably you have to add some filter for change only these rdKey you wqant. Else you can try with ObjectMapper from [Jackson (Example)](http://tutorials.jenkov.com/java-json/jackson-objectmapper.html) but there you have to build the complete structure with objects, read it, make change at the correct place, and at the end rewrite it... – code4fun Oct 10 '17 at 10:06
  • @java4fun: I'm aware about Jackson API, but If I want to use that, then need to create the java objects matching json structure. And it will increase the complexity of task. – Punit Oct 11 '17 at 09:24
  • @Punit Not necessary, you can read your json as map of objects with mapper.readValue(..., HashMap.class) – chimmi Oct 12 '17 at 11:25
  • Yes, but again it will map everything into key-value pair inside HashMap. Then, for getting "rdKey", need to traverse through the HashMap until I find it. It will be same or more effort as I put into the code I share in my question using org.json library. Please correct me if I'm wrong. – Punit Oct 12 '17 at 12:20