From 759ecf35b646b0928e6594a9b0c7290d28bb29be Mon Sep 17 00:00:00 2001 From: kalle Date: Fri, 4 Feb 2011 23:15:46 +0100 Subject: [PATCH] implemented naive eval function to remove java ScriptEngine dependency (support for java 5) --- .../java/com/jayway/jsonpath/PathUtil.java | 4 +- .../com/jayway/jsonpath/eval/Expression.java | 88 +++++++++++++++++++ .../filter/JsonPathFilterFactory.java | 3 +- .../jayway/jsonpath/filter/ListFilter.java | 47 ++++------ .../jayway/jsonpath/ExpressionEvalTest.java | 65 ++++++++++++++ .../com/jayway/jsonpath/JsonPathTest.java | 1 + 6 files changed, 176 insertions(+), 32 deletions(-) create mode 100644 json-path/src/main/java/com/jayway/jsonpath/eval/Expression.java create mode 100644 json-path/src/test/java/com/jayway/jsonpath/ExpressionEvalTest.java diff --git a/json-path/src/main/java/com/jayway/jsonpath/PathUtil.java b/json-path/src/main/java/com/jayway/jsonpath/PathUtil.java index a03e6d82..a43056ac 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/PathUtil.java +++ b/json-path/src/main/java/com/jayway/jsonpath/PathUtil.java @@ -53,7 +53,9 @@ public class PathUtil { jsonPath = jsonPath.replace("..", ".~.") .replace("[", ".[") - .replace("@.", "@"); + .replace("@.", "@") + .replace("['", "") + .replace("']", ""); String[] split = jsonPath.split("\\."); diff --git a/json-path/src/main/java/com/jayway/jsonpath/eval/Expression.java b/json-path/src/main/java/com/jayway/jsonpath/eval/Expression.java new file mode 100644 index 00000000..1081896e --- /dev/null +++ b/json-path/src/main/java/com/jayway/jsonpath/eval/Expression.java @@ -0,0 +1,88 @@ +package com.jayway.jsonpath.eval; + +/** + * User: kalle stenflo + * Date: 2/4/11 + * Time: 9:21 PM + */ +public class Expression { + + + public static boolean eval(T actual, String comparator, String expected) { + + comparator = comparator.trim(); + + if (actual instanceof Long) { + + Long a = (Long) actual; + Long e = Long.parseLong(expected.trim()); + + if ("=".equals(comparator)) { + return a.longValue() == e.longValue(); + } else if ("!=".equals(comparator) || "<>".equals(comparator)) { + return a.longValue() != e.longValue(); + } else if (">".equals(comparator)) { + return a.longValue() > e.longValue(); + } else if (">=".equals(comparator)) { + return a.longValue() >= e.longValue(); + } else if ("<".equals(comparator)) { + return a.longValue() < e.longValue(); + } else if ("<=".equals(comparator)) { + return a.longValue() <= e.longValue(); + } + } else if (actual instanceof Integer) { + Integer a = (Integer) actual; + Integer e = Integer.parseInt(expected.trim()); + + if ("=".equals(comparator)) { + return a.longValue() == e.longValue(); + } else if ("!=".equals(comparator) || "<>".equals(comparator)) { + return a.longValue() != e.longValue(); + } else if (">".equals(comparator)) { + return a.longValue() > e.longValue(); + } else if (">=".equals(comparator)) { + return a.longValue() >= e.longValue(); + } else if ("<".equals(comparator)) { + return a.longValue() < e.longValue(); + } else if ("<=".equals(comparator)) { + return a.longValue() <= e.longValue(); + } + } else if (actual instanceof Double) { + + Double a = (Double) actual; + Double e = Double.parseDouble(expected.trim()); + + if ("=".equals(comparator)) { + return a.longValue() == e.longValue(); + } else if ("!=".equals(comparator) || "<>".equals(comparator)) { + return a.longValue() != e.longValue(); + } else if (">".equals(comparator)) { + return a.longValue() > e.longValue(); + } else if (">=".equals(comparator)) { + return a.longValue() >= e.longValue(); + } else if ("<".equals(comparator)) { + return a.longValue() < e.longValue(); + } else if ("<=".equals(comparator)) { + return a.longValue() <= e.longValue(); + } + } else if (actual instanceof String) { + + String a = (String)actual; + expected = expected.trim(); + if(expected.startsWith("'")) { + expected = expected.substring(1); + } + if(expected.endsWith("'")){ + expected = expected.substring(0, expected.length()-1); + } + + if ("=".equals(comparator)) { + return a.equals(expected); + } else if ("!=".equals(comparator) || "<>".equals(comparator)) { + return !a.equals(expected); + } + } + + return false; + } +} diff --git a/json-path/src/main/java/com/jayway/jsonpath/filter/JsonPathFilterFactory.java b/json-path/src/main/java/com/jayway/jsonpath/filter/JsonPathFilterFactory.java index e03377d2..3ed84afe 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/filter/JsonPathFilterFactory.java +++ b/json-path/src/main/java/com/jayway/jsonpath/filter/JsonPathFilterFactory.java @@ -10,7 +10,8 @@ import java.util.regex.Pattern; public class JsonPathFilterFactory { private final static Pattern ROOT_FILTER_PATTERN = Pattern.compile("\\$"); - private final static Pattern PROPERTY_FILTER_PATTERN = Pattern.compile("\\w+"); + private final static Pattern PROPERTY_FILTER_PATTERN = Pattern.compile("(\\w+)|\\['(\\w+)'\\]"); + //private final static Pattern PROPERTY_FILTER_PATTERN = Pattern.compile("\\w+"); private final static Pattern WILDCARD_PROPERTY_FILTER_PATTERN = Pattern.compile("\\*"); private final static Pattern LIST_FILTER_PATTERN = Pattern.compile("\\[.*?\\]"); private final static Pattern TRAVERSE_FILTER_PATTERN = Pattern.compile("\\.\\."); diff --git a/json-path/src/main/java/com/jayway/jsonpath/filter/ListFilter.java b/json-path/src/main/java/com/jayway/jsonpath/filter/ListFilter.java index 0ccbcf6b..b44acc1a 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/filter/ListFilter.java +++ b/json-path/src/main/java/com/jayway/jsonpath/filter/ListFilter.java @@ -1,11 +1,11 @@ package com.jayway.jsonpath.filter; import com.jayway.jsonpath.JsonUtil; +import com.jayway.jsonpath.eval.Expression; import org.json.simple.JSONArray; -import javax.script.ScriptEngine; -import javax.script.ScriptEngineManager; -import javax.script.ScriptException; +//import javax.script.ScriptEngine; +//import javax.script.ScriptEngineManager; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -20,7 +20,7 @@ import java.util.regex.Pattern; */ public class ListFilter extends JsonPathFilterBase { - private static ScriptEngine SCRIPT_ENGINE = new ScriptEngineManager().getEngineByName("js"); + //private static ScriptEngine SCRIPT_ENGINE = new ScriptEngineManager().getEngineByName("js"); private static final Pattern LIST_INDEX_PATTERN = Pattern.compile("\\[(\\s?\\d+\\s?,?)+\\]"); //[1] OR [1,2,3] private static final Pattern LIST_PULL_PATTERN = Pattern.compile("\\[\\s?:(\\d+)\\s?\\]"); //[ :2 ] @@ -51,8 +51,7 @@ public class ListFilter extends JsonPathFilterBase { return filterByPullIndex(items); } else if (LIST_ITEM_HAS_PROPERTY_PATTERN.matcher(pathFragment).matches()) { return filterByItemProperty(items); - } - else if (LIST_ITEM_MATCHES_EVAL.matcher(pathFragment).matches()) { + } else if (LIST_ITEM_MATCHES_EVAL.matcher(pathFragment).matches()) { return filterByItemEvalMatch(items); } @@ -64,7 +63,7 @@ public class ListFilter extends JsonPathFilterBase { for (Object current : items) { for (Object item : JsonUtil.toList(current)) { - if(isEvalMatch(item)){ + if (isEvalMatch(item)) { result.add(item); } } @@ -81,8 +80,8 @@ public class ListFilter extends JsonPathFilterBase { for (Object current : items) { for (Object item : JsonUtil.toList(current)) { - if(JsonUtil.isMap(item)){ - if(JsonUtil.toMap(item).containsKey(prop)) { + if (JsonUtil.isMap(item)) { + if (JsonUtil.toMap(item).containsKey(prop)) { result.add(item); } } @@ -142,43 +141,31 @@ public class ListFilter extends JsonPathFilterBase { Matcher matcher = LIST_ITEM_MATCHES_EVAL.matcher(pathFragment); if (matcher.matches()) { - String property = matcher.group(1); - String operator = matcher.group(2); - String expected = matcher.group(3); + String property = matcher.group(1); + String operator = matcher.group(2); + String expected = matcher.group(3); - if(!JsonUtil.isMap(check)){ + if (!JsonUtil.isMap(check)) { return false; } Map obj = JsonUtil.toMap(check); - if(!obj.containsKey(property)){ + if (!obj.containsKey(property)) { return false; } Object propertyValue = obj.get(property); - if(JsonUtil.isContainer(propertyValue)){ + if (JsonUtil.isContainer(propertyValue)) { return false; } - - if(propertyValue instanceof String){ - propertyValue = "'" + propertyValue + "'"; - } - - if(operator.trim().equals("=")){ - operator = "==="; - } - - String expression = propertyValue + " " + operator + " " + expected; System.out.println("EVAL" + expression); - try { - return (Boolean) SCRIPT_ENGINE.eval(expression); - } catch (ScriptException e) { - return false; - } + + return Expression.eval(propertyValue, operator, expected); + } return false; } diff --git a/json-path/src/test/java/com/jayway/jsonpath/ExpressionEvalTest.java b/json-path/src/test/java/com/jayway/jsonpath/ExpressionEvalTest.java new file mode 100644 index 00000000..bb9ca807 --- /dev/null +++ b/json-path/src/test/java/com/jayway/jsonpath/ExpressionEvalTest.java @@ -0,0 +1,65 @@ +package com.jayway.jsonpath; + +import com.jayway.jsonpath.eval.Expression; +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * Created by IntelliJ IDEA. + * User: kallestenflo + * Date: 2/4/11 + * Time: 9:32 PM + */ +public class ExpressionEvalTest { + + + @Test + public void long_eval() throws Exception { + + assertTrue(Expression.eval(1L, "=", "1")); + assertTrue(Expression.eval(2L, "!=", "1")); + assertTrue(Expression.eval(2L, ">", "1")); + assertTrue(Expression.eval(2L, ">=", "1")); + assertTrue(Expression.eval(2L, ">=", "2")); + assertTrue(Expression.eval(1L, "<", "2")); + assertTrue(Expression.eval(2L, "<=", "2")); + + assertFalse(Expression.eval(1, ">", "2")); + assertFalse(Expression.eval(1, ">=", "2")); + assertFalse(Expression.eval(2, "<", "1")); + assertFalse(Expression.eval(2, "<=", "1")); + assertFalse(Expression.eval(1, "=", "2")); + assertFalse(Expression.eval(1, "!=", "1")); + } + + @Test + public void double_eval() throws Exception { + + assertTrue(Expression.eval(1D, "=", "1")); + assertTrue(Expression.eval(2D, "!=", "1")); + assertTrue(Expression.eval(2D, ">", "1")); + assertTrue(Expression.eval(2D, ">=", "1")); + assertTrue(Expression.eval(2D, ">=", "2")); + assertTrue(Expression.eval(1D, "<", "2")); + assertTrue(Expression.eval(2D, "<=", "2")); + + assertFalse(Expression.eval(1D, ">", "2")); + assertFalse(Expression.eval(1D, ">=", "2")); + assertFalse(Expression.eval(2D, "<", "1")); + assertFalse(Expression.eval(2D, "<=", "1")); + assertFalse(Expression.eval(1D, "=", "2")); + assertFalse(Expression.eval(1D, "!=", "1")); + } + + @Test + public void string_eval() throws Exception { + + assertTrue(Expression.eval("A", "=", "A")); + assertTrue(Expression.eval("B", "!=", "A")); + + } + + +} diff --git a/json-path/src/test/java/com/jayway/jsonpath/JsonPathTest.java b/json-path/src/test/java/com/jayway/jsonpath/JsonPathTest.java index 47576bdb..5cd5b17b 100644 --- a/json-path/src/test/java/com/jayway/jsonpath/JsonPathTest.java +++ b/json-path/src/test/java/com/jayway/jsonpath/JsonPathTest.java @@ -86,6 +86,7 @@ public class JsonPathTest { @Test public void read_store_book_author() throws Exception { assertThat(JsonPath.read(DOCUMENT, "$.store.book[*].author"), hasItems("Nigel Rees", "Evelyn Waugh", "Herman Melville", "J. R. R. Tolkien")); + assertThat(JsonPath.read(DOCUMENT, "$.['store'].['book'][*].['author']"), hasItems("Nigel Rees", "Evelyn Waugh", "Herman Melville", "J. R. R. Tolkien")); }