0

I have a nested json like below. From this I want to get specific values which are not again json objects. e.g. values against keys "first_name" or "last_name" or "purpose" etc

[
   {
      "purpose":"Audit",
      "sender_name":"Tester One",
      "sent_date":"10-10-2020",
      "approval":true,
      "agency":{
         "name":"Test Agency",
         "id":1234
      },
      "records":[
         {
            "students":{
               "first_name":"FirstOne",
               "last_name":"LastOne",
               "address":{
                  "street":"123 Street",
                  "city":"Test City",
                  "zip":12345
               }
            },
            "employees":{
               "first_name":"EmpFirst",
               "last_name":"EmpLast",
               "address":{
                  "street":"ABC Street",
                  "city":"ABC City",
                  "zip":99921
               }
            }
         }
      ],
      "completion":true
   }
]

For this I wrote 2 recursive methods and another method which will invoke this method. Following is my code.

public class JsonUtils {

    private static ArrayList<Object> resultSet = new ArrayList<Object>();
    
    /*Method to convert json to Map*/
    public static Map<String, Object> convertJsonArrayToMap(String filePath) {
        List<Object> list = null;
        ObjectMapper mapper = new ObjectMapper();
        try {
            list = mapper.readValue(new File(filePath), new TypeReference<List<Object>>() {
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
        Map<String, Object> data = (Map<String, Object>) list.get(0);
        return data;
    }
    
    /*Method to iterate nested HashMap*/
    public static Object jsonMapIterator(Map<String, Object> map, String key) {
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            if (entry.getValue() instanceof Map) {
                jsonMapIterator((Map<String, Object>) entry.getValue(), key);
            } else if (entry.getValue() instanceof ArrayList) {
                jsonListIterator((ArrayList<Object>) entry.getValue(), key);
            } else {
                if (entry.getKey() == key) resultSet.add(entry.getValue());
            }
        }
        return resultSet!=null?resultSet:null;
    }
    
    /*Method to iterate array list of objects*/
    public static Object jsonListIterator(ArrayList<Object> list, String key) {
        AtomicReference<Object> value = null;
        Consumer<Object> action = i -> {
            if (i instanceof ArrayList) {
                jsonListIterator((ArrayList<Object>) i, key);
            } else if (i instanceof Map) {
                jsonMapIterator((Map<String, Object>) i, key);
            } else {
                value.set(i);
            }
        };
        list.stream().forEach(action);
        return value;
    }
    
    /*method to invoke recursive search and return all values for any given key*/
    public static Object jsonValueFetcher(Map<String, Object> jsonData, String key){
        resultSet.clear();
        ArrayList<Object> values;
        values = (ArrayList<Object>) jsonMapIterator(jsonData, key);
        return values.size()==0?null:values;
    }

    public static void main(String[] args) {
       Map<String, Object> jsonData = convertJsonArrayToMap("src/test/resources/nestedJson.json");
        System.out.println(jsonValueFetcher(jsonData,"first_name"));
    }
}

Now in here, how can I make the static variable resultSet and the two recursive methods thread safe in case of a parallel test execution?

Reshmy
  • 26
  • 1
  • 2
    Synchronize on a lock? – Slaw Jul 17 '21 at 05:07
  • Do you want to convert different JSON values to `Map`s concurrently? In this case, not using a `static` variable but passing the `List` around from method to method might help. [Thread confinement](https://stackoverflow.com/a/6261976/10871900) might be what you are looking for in this case. This would make it so you don't need any synchronisation. – dan1st Jul 17 '21 at 05:12
  • Make the field and the methods non-static and create an instance for each test. – tgdavies Jul 17 '21 at 05:20

0 Answers0