package nl.hsac.fitnesse.fixture.util; import net.minidev.json.JSONArray; import nl.hsac.fitnesse.fixture.Environment; import org.apache.commons.lang3.StringUtils; import org.json.JSONException; import org.json.JSONObject; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; /** * Helper dealing with JSON objects. */ public class JsonHelper implements Formatter { /** * Creates formatted version of the supplied JSON. * @param json JSON to format. * @return formatted version. */ public String format(String json) { String result = null; if (json != null){ result = new JSONObject(json).toString(4); } return result; } /** * Interprets supplied String as Json and converts it into a Map. * @param jsonString string to interpret as Json object. * @return property -> value. */ public Map<String, Object> jsonStringToMap(String jsonString) { if (StringUtils.isEmpty(jsonString)) { return null; } JSONObject jsonObject; try { jsonObject = new JSONObject(jsonString); return jsonObjectToMap(jsonObject); } catch (JSONException e) { throw new RuntimeException("Unable to convert string to map: " + jsonString, e); } } private Map<String, Object> jsonObjectToMap(JSONObject jsonObject) throws JSONException { Map<String, Object> result = new LinkedHashMap<>(); for (Object key : jsonObject.keySet()) { String stringKey = String.valueOf(key); Object value = convertJsonObject(jsonObject.get(stringKey)); result.put(stringKey, value); } return result; } private Object convertJsonObject(Object value) { Object result = value; if (value instanceof JSONObject) { result = jsonObjectToMap((JSONObject) value); } else if (value instanceof org.json.JSONArray) { List<Object> newVal = new ArrayList<>(); for (Object o : (org.json.JSONArray) value) { newVal.add(convertJsonObject(o)); } result = newVal; } return result; } /** * Sorts an array in a json object. * @param json json document. * @param arrayExpr JsonPath expression to select array to sort. * @param nestedPathExpr JsonPath expression to select value of array's elements to sort them on. * @return json document with specified array sorted. */ public String sort(String json, String arrayExpr, String nestedPathExpr) { JsonPathHelper pathHelper = getPathHelper(); Object topLevel = pathHelper.getJsonPath(json, arrayExpr); if (topLevel instanceof JSONArray) { JSONArray a = (JSONArray) topLevel; JSONArray aSorted = sort(pathHelper, a, nestedPathExpr); return pathHelper.updateJsonPathWithValue(json, arrayExpr, aSorted); } else { throw new IllegalArgumentException("Unable to find array using: " + arrayExpr); } } private JSONArray sort(final JsonPathHelper pathHelper, JSONArray a, final String nestedPathExpr) { List<String> elements = new ArrayList<>(a.size()); for (Object element : a) { net.minidev.json.JSONObject jsonObject = new net.minidev.json.JSONObject((Map<String, ?>) element); elements.add(jsonObject.toJSONString()); } Collections.sort(elements, new Comparator<String>() { @Override public int compare(String o1, String o2) { Comparable val1 = (Comparable) pathHelper.getJsonPath(o1, nestedPathExpr); Comparable val2 = (Comparable) pathHelper.getJsonPath(o2, nestedPathExpr); return val1.compareTo(val2); } }); return convertToArray(elements); } private JSONArray convertToArray(List<String> elements) { List<Map<String, Object>> result = new ArrayList<>(elements.size()); for (String str : elements) { Map<String, Object> map = jsonStringToMap(str); result.add(map); } JSONArray array = new JSONArray(); array.addAll(result); return array; } public JsonPathHelper getPathHelper() { return Environment.getInstance().getJsonPathHelper(); } }