Thursday, April 2, 2020

Construct complex nested JSON file based on a list of JSON path

What happened was my QAs did not want to change their mind to prepare data in Excel, using 'path' concept. They're too used to that method already since the XML time. They'd like to continue the same. Row contains Path and Cell/Column contains value. Each Cell/Column represents one test case. Sounds good?

I googled and googled and tried so many solutions suggested by a lot of kind men in StackOverflow, none of the solutions really gave me what I wanted. No one really did this before that building a complex/complicated nested JSON file. I decided to write the algorithm myself. 

How does the so called complex/nested look like? It looks like below. And I had to build the JSON from this list of paths. 

$.JSONDoc.OC.AL.data_type
$.JSONDoc.OC.AL.value
$.JSONDoc.OC.SIG.data_type
$.JSONDoc.OC.SIG.value
$.JSONDoc.IN.MCPL.PRODTYPE.data_type
$.JSONDoc.IN.USER.COUNTRYCODE.data_type
$.JSONDoc.IN.USER.COUNTRYCODE.value
$.JSONDoc.IN.MCPL.LOCATION.COUNTRY.data_type
$.JSONDoc.IN.MCPL.LOCATION.COUNTRY.value
$.JSONDoc.IN.USER.FRSCR.data_type
$.JSONDoc.IN.USER.FRSCR.value
$.JSONDoc.IN.MCPL.ITEMS.value[0].QUANTITY.data_type
$.JSONDoc.IN.MCPL.ITEMS.value[0].QUANTITY.value
$.JSONDoc.IN.CLU.SPLT180.data_type
$.JSONDoc.IN.CLU.SPLT180.value
$.JSONDoc.OUT.TXN.FRC.data_type
$.JSONDoc.OUT.TXN.FRC.value[0]

The algorithm below works well so far for any JSON path that consists of JSON Array as well. I know it's not perfect but I really hope it's helpful to you guys who've bumped into the similar issue that I had. One thing to note is that the 'has' method from JSONObject does not really give accurate result if the JSONObject has multi-level of nested JSONObject. Therefore I also wrote one for myself. 

public static JSONObject createJSONObject(String[] keys, int index, String value, JSONArray jArray, JSONObject masterJObj) {
        if (index < keys.length) {
            String key = keys[index];
            String nextKey = keys[index + 1];
            if (key.contains("[")) {
                return createJSONObject(keys, index + 1, value, jArray, masterJObj);
            }
            if ((index < keys.length - 2) && nextKey.contains("[")) {
                JSONArray jsonArray = new JSONArray();
                JSONObject jobj = new JSONObject();
                Object obj2 = getObject(masterJObj, key);
                if (obj2 != null) {
                    if (obj2 instanceof JSONObject) {
                        jobj = (JSONObject) obj2;
                        if (jobj.has(nextKey)) {
                            jsonArray = jobj.getJSONArray(nextKey);
                        }
                    }
                }
                createJSONObject(keys, index + 1, value, jsonArray, masterJObj);
                jobj.put(nextKey, jsonArray);
                return jobj;
            } else {
                JSONObject jsonObject1 = null;
                if (jArray != null) {
                    if (!jArray.isEmpty()) {
                        for (int j = 0; j < jArray.length(); j++) {
                            jsonObject1 = jArray.getJSONObject(j);
                            jArray = null;
                            break;
                        }
                    } else {
                        JSONObject jsonObject2 = new JSONObject();
                        jsonObject1 = new JSONObject();
                        jsonObject1.put(key, jsonObject2);
                        jArray.put(jsonObject1);
                    }
                } else {
                    Object obj1 = getObject(masterJObj, key);
                    if (obj1 != null) {
                        jsonObject1 = (JSONObject) obj1;
                    }
                }
                if (jsonObject1 == null) {
                    jsonObject1 = new JSONObject();
                }
                if (index == keys.length - 2) {
                    JSONObject jsonObject2;
                    if (jsonObject1.has(key)) {
                        jsonObject2 = jsonObject1.getJSONObject(key);
                    } else {
                        jsonObject2 = new JSONObject();
                    }
                    if (nextKey.contains("[")) {
                        nextKey = nextKey.substring(0, nextKey.indexOf("["));
                        JSONArray jArray1 = new JSONArray();;
                        if (!jsonObject1.isEmpty() && jsonObject1.has(nextKey)) {
                            jArray1 = jsonObject1.getJSONArray(nextKey);
                        }
                        jArray1.put(value);
                        jsonObject1.put(nextKey, jArray1);
                    } else {
                        if (!jsonObject1.isEmpty()) {
                            if (jsonObject1.has(key)) {
                                JSONObject jsonObject3 = jsonObject1.getJSONObject(key);
                                jsonObject3.put(nextKey, value);
                            } else {
                                jsonObject1.put(nextKey, value);
                            }
                        } else {
                            jsonObject2.put(nextKey, value);
                            jsonObject1.put(key, jsonObject2);
                        }
                    }
                    return jsonObject1;
                } else {
                    JSONObject returnedJObj = createJSONObject(keys, index + 1, value, jArray, masterJObj);
                    if (returnedJObj != null) {
                        if (returnedJObj.has(nextKey)) {
                            jsonObject1 = returnedJObj;
                        } else {
                            if (jsonObject1.has(nextKey)) {
                                if (!returnedJObj.isEmpty()) {
                                    String nextNextKey = returnedJObj.keys().next();
                                    Object jObj3 = returnedJObj.get(nextNextKey);
                                    if (jObj3 instanceof JSONObject) {
                                        jsonObject1.getJSONObject(nextKey).put(nextNextKey, jObj3);
                                    }
                                }
                            } else {
                                jsonObject1.put(nextKey, returnedJObj);
                            }
                        }
                    }
                }
                return jsonObject1;
            }
        }
        return null;
    }
    public static Object getObject(Object object, String searchedKey) {
        if (object instanceof JSONObject) {
            JSONObject jsonObject = (JSONObject) object;
            Iterator itr = jsonObject.keys();
            while (itr.hasNext()) {
                String key = (String) itr.next();
                if (!searchedKey.equals(key)) {
                    Object obj = getObject(jsonObject.get(key), searchedKey);
                    if (obj != null) {
                        return obj;
                    }
                } else {
                    return jsonObject.get(key);
                }
            }
        } else if (object instanceof JSONArray) {
            JSONArray jsonArray = (JSONArray) object;
            return getObjectFromJSONArray(jsonArray, searchedKey);
        }

        return null;
    }