code: private void traverseJsonData(JSONObject jsonData, String jsonPath, TestContext context) {
          for (Iterator it = jsonData.entrySet().iterator(); it.hasNext();) {
              Map.Entry jsonEntry = (Map.Entry) it.next();
  
              if (jsonEntry.getValue() instanceof JSONObject) {
                  traverseJsonData((JSONObject) jsonEntry.getValue(), (StringUtils.hasText(jsonPath) ? jsonPath + "." + jsonEntry.getKey() : jsonEntry.getKey().toString()), context);
              } else if (jsonEntry.getValue() instanceof JSONArray) {
                  JSONArray jsonArray = (JSONArray) jsonEntry.getValue();
                  for (int i = 0; i < jsonArray.size(); i++) {
                      if (jsonArray.get(i) instanceof JSONObject) {
                          traverseJsonData((JSONObject) jsonArray.get(i), String.format((StringUtils.hasText(jsonPath) ? jsonPath + "." + jsonEntry.getKey() : jsonEntry.getKey().toString()) + "[%s]", i), context);
                      } else {
                          jsonArray.set(i, translate(String.format((StringUtils.hasText(jsonPath) ? jsonPath + "." + jsonEntry.getKey() : jsonEntry.getKey().toString()) + "[%s]", i), jsonArray.get(i), context));
                      }
                  }
              } else {
                  jsonEntry.setValue(translate((StringUtils.hasText(jsonPath) ? jsonPath + "." + jsonEntry.getKey() : jsonEntry.getKey().toString()),
                          jsonEntry.getValue() != null ? jsonEntry.getValue() : null, context));
              }
          }
      }
docs: Walks through the Json object structure and translates values based on element path if necessary.
  @param jsonData
  @param jsonPath
  @param context