diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/CharacterIndex.java b/json-path/src/main/java/com/jayway/jsonpath/internal/CharacterIndex.java index 1aa28679..378d5c4b 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/CharacterIndex.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/CharacterIndex.java @@ -220,16 +220,17 @@ public class CharacterIndex { incrementPosition(1); } - public void readSignificantSubSequence(CharSequence s) { + public boolean hasSignificantSubSequence(CharSequence s) { skipBlanks(); if (! inBounds(position + s.length() - 1)) { - throw new InvalidPathException(String.format("End of string reached while expecting: %s", s)); + return false; } if (! subSequence(position, position + s.length()).equals(s)) { - throw new InvalidPathException(String.format("Expected: %s", s)); + return false; } incrementPosition(s.length()); + return true; } public int indexOfPreviousSignificantChar(int startPosition){ @@ -314,4 +315,4 @@ public class CharacterIndex { skipBlanksAtEnd(); return this; } -} \ No newline at end of file +} diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/FilterCompiler.java b/json-path/src/main/java/com/jayway/jsonpath/internal/filter/FilterCompiler.java index 67b512e4..f6b9f2d3 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/FilterCompiler.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/filter/FilterCompiler.java @@ -132,11 +132,9 @@ public class FilterCompiler { while (true) { int savepoint = filter.position(); - try { - filter.readSignificantSubSequence(LogicalOperator.OR.getOperatorString()); + if (filter.hasSignificantSubSequence(LogicalOperator.OR.getOperatorString())) { ops.add(readLogicalAND()); - } - catch (InvalidPathException exc) { + } else { filter.setPosition(savepoint); break; } @@ -152,11 +150,9 @@ public class FilterCompiler { while (true) { int savepoint = filter.position(); - try { - filter.readSignificantSubSequence(LogicalOperator.AND.getOperatorString()); + if (filter.hasSignificantSubSequence(LogicalOperator.AND.getOperatorString())) { ops.add(readLogicalANDOperand()); - } - catch (InvalidPathException exc) { + } else { filter.setPosition(savepoint); break; } diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/ValueNode.java b/json-path/src/main/java/com/jayway/jsonpath/internal/filter/ValueNode.java index d1619c45..23afe785 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/filter/ValueNode.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/filter/ValueNode.java @@ -402,18 +402,19 @@ public abstract class ValueNode { private boolean useSingleQuote = true; private StringNode(CharSequence charSequence, boolean escape) { - if(charSequence.length() > 1){ + if (escape && charSequence.length() > 1) { char open = charSequence.charAt(0); char close = charSequence.charAt(charSequence.length()-1); - - if(open == '\'' && close == '\''){ + if (open == '\'' && close == '\'') { charSequence = charSequence.subSequence(1, charSequence.length()-1); - } else if(open == '"' && close == '"'){ + } else if (open == '"' && close == '"') { charSequence = charSequence.subSequence(1, charSequence.length()-1); useSingleQuote = false; } + string = Utils.unescape(charSequence.toString()); + } else { + string = charSequence.toString(); } - string = escape ? Utils.unescape(charSequence.toString()) : charSequence.toString(); } @Override diff --git a/json-path/src/test/java/com/jayway/jsonpath/MultiPropTest.java b/json-path/src/test/java/com/jayway/jsonpath/MultiPropTest.java index fc5567a8..de5824b9 100644 --- a/json-path/src/test/java/com/jayway/jsonpath/MultiPropTest.java +++ b/json-path/src/test/java/com/jayway/jsonpath/MultiPropTest.java @@ -3,6 +3,7 @@ package com.jayway.jsonpath; import org.junit.Test; import java.util.HashMap; +import java.util.List; import java.util.Map; import static com.jayway.jsonpath.JsonPath.using; @@ -114,7 +115,7 @@ public class MultiPropTest { final Configuration conf = Configuration.defaultConfiguration().addOptions(Option.REQUIRE_PROPERTIES); final String json = "{\"a\": {\"v\": 5}, \"b\": {\"v\": 4}, \"c\": {\"v\": 1}}"; - assertThat(using(conf).parse(json).read("$['a', 'c'].v")).asList().containsOnly(5, 1); + assertThat((List)using(conf).parse(json).read("$['a', 'c'].v")).asList().containsOnly(5, 1); assertEvaluationThrows(json, "$['d', 'a', 'c', 'm'].v", PathNotFoundException.class, conf); } } diff --git a/json-path/src/test/java/com/jayway/jsonpath/OptionsTest.java b/json-path/src/test/java/com/jayway/jsonpath/OptionsTest.java index 1093ff7a..873b3b6a 100644 --- a/json-path/src/test/java/com/jayway/jsonpath/OptionsTest.java +++ b/json-path/src/test/java/com/jayway/jsonpath/OptionsTest.java @@ -21,7 +21,7 @@ public class OptionsTest extends BaseTest { Configuration conf = Configuration.defaultConfiguration(); - assertThat(using(conf).parse("{\"foo\" : \"bar\"}").read("$.baz")).isNull(); + assertThat((String)using(conf).parse("{\"foo\" : \"bar\"}").read("$.baz")).isNull(); } @Test @@ -37,7 +37,7 @@ public class OptionsTest extends BaseTest { Configuration conf = Configuration.defaultConfiguration(); - assertThat(using(conf).parse("{\"foo\" : \"bar\"}").read("$.foo")).isInstanceOf(String.class); + assertThat((String)using(conf).parse("{\"foo\" : \"bar\"}").read("$.foo")).isInstanceOf(String.class); } @Test @@ -45,11 +45,11 @@ public class OptionsTest extends BaseTest { Configuration conf = Configuration.builder().options(ALWAYS_RETURN_LIST).build(); - assertThat(using(conf).parse("{\"foo\" : \"bar\"}").read("$.foo")).isInstanceOf(List.class); + assertThat((List)using(conf).parse("{\"foo\" : \"bar\"}").read("$.foo")).isInstanceOf(List.class); - assertThat(using(conf).parse("{\"foo\": null}").read("$.foo")).isInstanceOf(List.class); + assertThat((List)using(conf).parse("{\"foo\": null}").read("$.foo")).isInstanceOf(List.class); - assertThat(using(conf).parse("{\"foo\": [1, 4, 8]}").read("$.foo")).asList() + assertThat((List)using(conf).parse("{\"foo\": [1, 4, 8]}").read("$.foo")).asList() .containsExactly(Arrays.asList(1, 4, 8)); } @@ -61,7 +61,7 @@ public class OptionsTest extends BaseTest { assertThat(result).hasSize(1); assertThat(result.get(0)).isNull(); - assertThat(using(conf).parse("{\"bar\": {\"foo\": [1, 4, 8]}}").read("$..foo")).asList() + assertThat((List)using(conf).parse("{\"bar\": {\"foo\": [1, 4, 8]}}").read("$..foo")).asList() .containsExactly(Arrays.asList(1, 4, 8)); } @@ -69,7 +69,7 @@ public class OptionsTest extends BaseTest { public void a_path_evaluation_is_returned_as_VALUE_by_default() { Configuration conf = Configuration.defaultConfiguration(); - assertThat(using(conf).parse("{\"foo\" : \"bar\"}").read("$.foo")).isEqualTo("bar"); + assertThat((String)using(conf).parse("{\"foo\" : \"bar\"}").read("$.foo")).isEqualTo("bar"); } @Test @@ -142,13 +142,13 @@ public class OptionsTest extends BaseTest { public void issue_suppress_exceptions_does_not_break_indefinite_evaluation() { Configuration conf = Configuration.builder().options(SUPPRESS_EXCEPTIONS).build(); - assertThat(using(conf).parse("{\"foo2\": [5]}").read("$..foo2[0]")).asList().containsOnly(5); - assertThat(using(conf).parse("{\"foo\" : {\"foo2\": [5]}}").read("$..foo2[0]")).asList().containsOnly(5); - assertThat(using(conf).parse("[null, [{\"foo\" : {\"foo2\": [5]}}]]").read("$..foo2[0]")).asList().containsOnly(5); + assertThat((List)using(conf).parse("{\"foo2\": [5]}").read("$..foo2[0]")).asList().containsOnly(5); + assertThat((List)using(conf).parse("{\"foo\" : {\"foo2\": [5]}}").read("$..foo2[0]")).asList().containsOnly(5); + assertThat((List)using(conf).parse("[null, [{\"foo\" : {\"foo2\": [5]}}]]").read("$..foo2[0]")).asList().containsOnly(5); - assertThat(using(conf).parse("[null, [{\"foo\" : {\"foo2\": [5]}}]]").read("$..foo.foo2[0]")).asList().containsOnly(5); + assertThat((List)using(conf).parse("[null, [{\"foo\" : {\"foo2\": [5]}}]]").read("$..foo.foo2[0]")).asList().containsOnly(5); - assertThat(using(conf).parse("{\"aoo\" : {}, \"foo\" : {\"foo2\": [5]}, \"zoo\" : {}}").read("$[*].foo2[0]")).asList().containsOnly(5); + assertThat((List)using(conf).parse("{\"aoo\" : {}, \"foo\" : {\"foo2\": [5]}, \"zoo\" : {}}").read("$[*].foo2[0]")).asList().containsOnly(5); } @Test diff --git a/json-path/src/test/java/com/jayway/jsonpath/PathCompilerTest.java b/json-path/src/test/java/com/jayway/jsonpath/PathCompilerTest.java index 699ba631..e8b7bfe6 100644 --- a/json-path/src/test/java/com/jayway/jsonpath/PathCompilerTest.java +++ b/json-path/src/test/java/com/jayway/jsonpath/PathCompilerTest.java @@ -1,5 +1,6 @@ package com.jayway.jsonpath; +import com.jayway.jsonpath.internal.ParseContextImpl; import org.junit.Ignore; import org.junit.Test; @@ -236,6 +237,49 @@ public class PathCompilerTest { assertThat(result).hasSize(1); } + @Test + public void issue_predicate_can_have_double_quotes() { + String json = "{\n" + + " \"logs\": [\n" + + " {\n" + + " \"message\": \"\\\"it\\\"\",\n" + + " }\n" + + " ]\n" + + "}"; + List result = JsonPath.read(json, "$.logs[?(@.message == '\"it\"')].message"); + assertThat(result).containsExactly("\"it\""); + } + + @Test + public void issue_predicate_can_have_single_quotes() { + String json = "{\n" + + " \"logs\": [\n" + + " {\n" + + " \"message\": \"'it'\",\n" + + " }\n" + + " ]\n" + + "}"; + DocumentContext parse = JsonPath.parse(json); + JsonPath compile = JsonPath.compile("$.logs[?(@.message == \"'it'\")].message"); + List result = parse.read(compile); + assertThat(result).containsExactly("'it'"); + } + + @Test + public void issue_predicate_can_have_single_quotes_escaped() { + String json = "{\n" + + " \"logs\": [\n" + + " {\n" + + " \"message\": \"'it'\",\n" + + " }\n" + + " ]\n" + + "}"; + DocumentContext parse = JsonPath.parse(json); + JsonPath compile = JsonPath.compile("$.logs[?(@.message == '\\'it\\'')].message"); + List result = parse.read(compile); + assertThat(result).containsExactly("'it'"); + } + @Test public void issue_predicate_can_have_square_bracket_in_prop() { String json = "{\n" diff --git a/json-path/src/test/java/com/jayway/jsonpath/ReturnTypeTest.java b/json-path/src/test/java/com/jayway/jsonpath/ReturnTypeTest.java index 144817a3..c9b3fb3b 100644 --- a/json-path/src/test/java/com/jayway/jsonpath/ReturnTypeTest.java +++ b/json-path/src/test/java/com/jayway/jsonpath/ReturnTypeTest.java @@ -18,7 +18,7 @@ public class ReturnTypeTest extends BaseTest { @Test public void assert_strings_can_be_read() { - assertThat(reader.read("$.string-property")).isEqualTo("string-value"); + assertThat((String)reader.read("$.string-property")).isEqualTo("string-value"); } @Test @@ -28,17 +28,17 @@ public class ReturnTypeTest extends BaseTest { @Test public void assert_longs_can_be_read() { - assertThat(reader.read("$.long-max-property")).isEqualTo(Long.MAX_VALUE); + assertThat((Long)reader.read("$.long-max-property")).isEqualTo(Long.MAX_VALUE); } @Test public void assert_boolean_values_can_be_read() { - assertThat(reader.read("$.boolean-property")).isEqualTo(true); + assertThat((Boolean)reader.read("$.boolean-property")).isEqualTo(true); } @Test public void assert_null_values_can_be_read() { - assertThat(reader.read("$.null-property")).isNull(); + assertThat((String)reader.read("$.null-property")).isNull(); } @Test diff --git a/json-path/src/test/java/com/jayway/jsonpath/old/IssuesTest.java b/json-path/src/test/java/com/jayway/jsonpath/old/IssuesTest.java index d66313bb..9dc4d5dc 100644 --- a/json-path/src/test/java/com/jayway/jsonpath/old/IssuesTest.java +++ b/json-path/src/test/java/com/jayway/jsonpath/old/IssuesTest.java @@ -431,7 +431,7 @@ public class IssuesTest extends BaseTest { "]"; - assertEquals(1, read(json, "$[0].a")); + assertEquals(Integer.valueOf(1), read(json, "$[0].a")); } @Test(expected = PathNotFoundException.class) @@ -471,9 +471,9 @@ public class IssuesTest extends BaseTest { String json = "{\"test\":null}"; - assertThat(read(json, "test")).isNull(); + assertThat((String)read(json, "test")).isNull(); - assertThat(JsonPath.using(Configuration.defaultConfiguration().setOptions(Option.SUPPRESS_EXCEPTIONS)).parse(json).read("nonExistingProperty")).isNull(); + assertThat((String)JsonPath.using(Configuration.defaultConfiguration().setOptions(Option.SUPPRESS_EXCEPTIONS)).parse(json).read("nonExistingProperty")).isNull(); try { read(json, "nonExistingProperty"); @@ -498,7 +498,7 @@ public class IssuesTest extends BaseTest { public void issue_45() { String json = "{\"rootkey\":{\"sub.key\":\"value\"}}"; - assertThat(read(json, "rootkey['sub.key']")).isEqualTo("value"); + assertThat((String)read(json, "rootkey['sub.key']")).isEqualTo("value"); } @Test @@ -508,7 +508,7 @@ public class IssuesTest extends BaseTest { String json = "{\"a\": {}}"; Configuration configuration = Configuration.defaultConfiguration().setOptions(Option.SUPPRESS_EXCEPTIONS); - assertThat(JsonPath.using(configuration).parse(json).read("a.x")).isNull(); + assertThat((String)JsonPath.using(configuration).parse(json).read("a.x")).isNull(); try { read(json, "a.x"); @@ -1018,8 +1018,8 @@ public class IssuesTest extends BaseTest { DocumentContext doc = JsonPath.parse(json).set("$.jsonArr[1].name", "Jayway"); - assertThat(doc.read("$.jsonArr[0].name")).isEqualTo("nOne"); - assertThat(doc.read("$.jsonArr[1].name")).isEqualTo("Jayway"); + assertThat((String)doc.read("$.jsonArr[0].name")).isEqualTo("nOne"); + assertThat((String)doc.read("$.jsonArr[1].name")).isEqualTo("Jayway"); } @Test diff --git a/json-path/src/test/java/com/jayway/jsonpath/old/JsonPathTest.java b/json-path/src/test/java/com/jayway/jsonpath/old/JsonPathTest.java index 60304267..81c6203d 100644 --- a/json-path/src/test/java/com/jayway/jsonpath/old/JsonPathTest.java +++ b/json-path/src/test/java/com/jayway/jsonpath/old/JsonPathTest.java @@ -133,7 +133,7 @@ public class JsonPathTest extends BaseTest { Assertions.fail("Expected PathNotFoundException"); } catch (PathNotFoundException e) { } - Assertions.assertThat(JsonPath.read(json, "$.data2.passes[0].id")).isEqualTo("1"); + Assertions.assertThat((String)JsonPath.read(json, "$.data2.passes[0].id")).isEqualTo("1"); } @Test