package tzatziki.util; import com.fasterxml.jackson.databind.JsonNode; /** * @author <a href="http://twitter.com/aloyer">@aloyer</a> */ public class JsonPath { private final String expr; public JsonPath(String expr) { this.expr = expr; } public JsonNode evaluate(JsonNode node) { return evaluate(node, expr); } public String evaluateString(JsonNode node) { JsonNode found = evaluate(node); if (found == null) return null; return found.textValue(); } private JsonNode evaluate(JsonNode node, String expr) { String[] path = removeTrailingSlash(expr).split("/"); JsonNode tNode = node; for (String pathFragment : path) { tNode = evaluateLocally(tNode, pathFragment); } return tNode; } private JsonNode evaluateLocally(JsonNode tNode, String pathFragment) { if (hasIndexedValue(pathFragment)) { return indexedValue(tNode, pathFragment); } return tNode.get(pathFragment); } private JsonNode indexedValue(JsonNode node, String pathFragment) { int startOf = pathFragment.lastIndexOf("["); int endOf = pathFragment.lastIndexOf("]"); if (startOf == -1 || endOf == -1) throw new InvalidExpressionException("Unbalanced '[' and ']' from fragment: '" + pathFragment + "'"); String idxAsString = pathFragment.substring(startOf + 1, endOf); int index = Integer.parseInt(idxAsString); String subPath = pathFragment.substring(0, startOf); JsonNode sub = evaluateLocally(node, subPath); return sub.get(index); } private boolean hasIndexedValue(String path) { return path.contains("["); } private static String removeTrailingSlash(String expr) { return expr.startsWith("/") ? expr.substring(1) : expr; } public static class InvalidExpressionException extends RuntimeException { public InvalidExpressionException(String message) { super(message); } } }