Browse Source

2.3 merge update: Also fix for quote evaluation

This is a problem in JsonPath where the left-hand side string value was being
quoted by mistake.

Issue 410 on github: https://github.com/json-path/JsonPath/issues/

Also fix issue 409 as well. This should improve performance a bit when parsing.

There are casts because the compiler in IntelliJ was confused as to what overloaded
method to call. Casts don't really hurt.
pull/416/head
Elias Ross 7 years ago
parent
commit
f6336650f2
  1. 9
      json-path/src/main/java/com/jayway/jsonpath/internal/CharacterIndex.java
  2. 12
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/FilterCompiler.java
  3. 11
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/ValueNode.java
  4. 3
      json-path/src/test/java/com/jayway/jsonpath/MultiPropTest.java
  5. 24
      json-path/src/test/java/com/jayway/jsonpath/OptionsTest.java
  6. 44
      json-path/src/test/java/com/jayway/jsonpath/PathCompilerTest.java
  7. 8
      json-path/src/test/java/com/jayway/jsonpath/ReturnTypeTest.java
  8. 14
      json-path/src/test/java/com/jayway/jsonpath/old/IssuesTest.java
  9. 2
      json-path/src/test/java/com/jayway/jsonpath/old/JsonPathTest.java

9
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;
}
}
}

12
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;
}

11
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

3
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);
}
}

24
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

44
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<String> 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<String> 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<String> result = parse.read(compile);
assertThat(result).containsExactly("'it'");
}
@Test
public void issue_predicate_can_have_square_bracket_in_prop() {
String json = "{\n"

8
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

14
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

2
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

Loading…
Cancel
Save