Browse Source

Bracket properties can contain path chars #154

pull/158/head
Kalle Stenflo 9 years ago
parent
commit
ea206498cc
  1. 18
      json-path/src/main/java/com/jayway/jsonpath/internal/CharacterIndex.java
  2. 3
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/FilterCompiler.java
  3. 4
      json-path/src/main/java/com/jayway/jsonpath/internal/path/PathCompiler.java
  4. 8
      json-path/src/main/java/com/jayway/jsonpath/internal/path/PathTokenFactory.java
  5. 6
      json-path/src/main/java/com/jayway/jsonpath/internal/path/PropertyPathToken.java
  6. 14
      json-path/src/test/java/com/jayway/jsonpath/FilterCompilerTest.java
  7. 2
      json-path/src/test/java/com/jayway/jsonpath/PathCompilerTest.java
  8. 2
      json-path/src/test/java/com/jayway/jsonpath/internal/path/PathTokenTest.java

18
json-path/src/main/java/com/jayway/jsonpath/internal/CharacterIndex.java

@ -10,6 +10,7 @@ public class CharacterIndex {
private static final char SPACE = ' '; private static final char SPACE = ' ';
private static final char ESCAPE = '\\'; private static final char ESCAPE = '\\';
private static final char SINGLE_QUOTE = '\''; private static final char SINGLE_QUOTE = '\'';
private static final char DOUBLE_QUOTE = '"';
private static final char MINUS = '-'; private static final char MINUS = '-';
private static final char PERIOD = '.'; private static final char PERIOD = '.';
private static final char REGEX = '/'; private static final char REGEX = '/';
@ -92,6 +93,23 @@ public class CharacterIndex {
break; break;
} }
} }
} else if (charAt(readPosition) == DOUBLE_QUOTE) {
boolean escaped = false;
while (inBounds(readPosition)) {
readPosition++;
if (escaped) {
escaped = false;
continue;
}
if (charAt(readPosition) == ESCAPE) {
escaped = true;
continue;
}
if (charAt(readPosition) == DOUBLE_QUOTE) {
readPosition++;
break;
}
}
} }
} }
if (skipRegex) { if (skipRegex) {

3
json-path/src/main/java/com/jayway/jsonpath/internal/filter/FilterCompiler.java

@ -16,6 +16,7 @@ public class FilterCompiler {
private static final char EVAL_CONTEXT = '@'; private static final char EVAL_CONTEXT = '@';
private static final char OPEN_SQUARE_BRACKET = '['; private static final char OPEN_SQUARE_BRACKET = '[';
private static final char CLOSE_SQUARE_BRACKET = ']';
private static final char OPEN_PARENTHESIS = '('; private static final char OPEN_PARENTHESIS = '(';
private static final char CLOSE_PARENTHESIS = ')'; private static final char CLOSE_PARENTHESIS = ')';
private static final char OPEN_OBJECT = '{'; private static final char OPEN_OBJECT = '{';
@ -301,7 +302,7 @@ public class FilterCompiler {
filter.incrementPosition(1); //skip $ and @ filter.incrementPosition(1); //skip $ and @
while (filter.inBounds()) { while (filter.inBounds()) {
if (filter.currentChar() == OPEN_SQUARE_BRACKET) { if (filter.currentChar() == OPEN_SQUARE_BRACKET) {
int closingSquareBracketIndex = filter.indexOfClosingSquareBracket(filter.position()); int closingSquareBracketIndex = filter.indexOfMatchingCloseChar(filter.position(), OPEN_SQUARE_BRACKET, CLOSE_SQUARE_BRACKET, true, false);
if (closingSquareBracketIndex == -1) { if (closingSquareBracketIndex == -1) {
throw new InvalidPathException("Square brackets does not match in filter " + filter); throw new InvalidPathException("Square brackets does not match in filter " + filter);
} else { } else {

4
json-path/src/main/java/com/jayway/jsonpath/internal/path/PathCompiler.java

@ -172,7 +172,7 @@ public class PathCompiler {
if(property.endsWith("()")){ if(property.endsWith("()")){
appender.appendPathToken(PathTokenFactory.createFunctionPathToken(property)); appender.appendPathToken(PathTokenFactory.createFunctionPathToken(property));
} else { } else {
appender.appendPathToken(PathTokenFactory.createSinglePropertyPathToken(property)); appender.appendPathToken(PathTokenFactory.createSinglePropertyPathToken(property, SINGLE_QUOTE));
} }
return path.currentIsTail() || readNextToken(appender); return path.currentIsTail() || readNextToken(appender);
@ -385,7 +385,7 @@ public class PathCompiler {
path.setPosition(endBracketIndex); path.setPosition(endBracketIndex);
appender.appendPathToken(PathTokenFactory.createPropertyPathToken(properties)); appender.appendPathToken(PathTokenFactory.createPropertyPathToken(properties, potentialStringDelimiter));
return path.currentIsTail() || readNextToken(appender); return path.currentIsTail() || readNextToken(appender);
} }

8
json-path/src/main/java/com/jayway/jsonpath/internal/path/PathTokenFactory.java

@ -13,12 +13,12 @@ public class PathTokenFactory {
return new RootPathToken(token); return new RootPathToken(token);
} }
public static PathToken createSinglePropertyPathToken(String property) { public static PathToken createSinglePropertyPathToken(String property, char stringDelimiter) {
return new PropertyPathToken(singletonList(property)); return new PropertyPathToken(singletonList(property), stringDelimiter);
} }
public static PathToken createPropertyPathToken(List<String> properties) { public static PathToken createPropertyPathToken(List<String> properties, char stringDelimiter) {
return new PropertyPathToken(properties); return new PropertyPathToken(properties, stringDelimiter);
} }
public static PathToken createSliceArrayPathToken(final ArraySliceOperation arraySliceOperation) { public static PathToken createSliceArrayPathToken(final ArraySliceOperation arraySliceOperation) {

6
json-path/src/main/java/com/jayway/jsonpath/internal/path/PropertyPathToken.java

@ -30,12 +30,14 @@ import static com.jayway.jsonpath.internal.Utils.onlyOneIsTrueNonThrow;
class PropertyPathToken extends PathToken { class PropertyPathToken extends PathToken {
private final List<String> properties; private final List<String> properties;
private final String stringDelimiter;
public PropertyPathToken(List<String> properties) { public PropertyPathToken(List<String> properties, char stringDelimiter) {
if (properties.isEmpty()) { if (properties.isEmpty()) {
throw new InvalidPathException("Empty properties"); throw new InvalidPathException("Empty properties");
} }
this.properties = properties; this.properties = properties;
this.stringDelimiter = Character.toString(stringDelimiter);
} }
public List<String> getProperties() { public List<String> getProperties() {
@ -97,7 +99,7 @@ class PropertyPathToken extends PathToken {
public String getPathFragment() { public String getPathFragment() {
return new StringBuilder() return new StringBuilder()
.append("[") .append("[")
.append(Utils.join(",", "'", properties)) .append(Utils.join(",", stringDelimiter, properties))
.append("]").toString(); .append("]").toString();
} }
} }

14
json-path/src/test/java/com/jayway/jsonpath/FilterCompilerTest.java

@ -42,18 +42,24 @@ public class FilterCompilerTest {
assertThat(compile("[?(((@)))]").toString()).isEqualTo("[?(@)]"); assertThat(compile("[?(((@)))]").toString()).isEqualTo("[?(@)]");
assertThat(compile("[?(@.name =~ /.*?/i)]").toString()).isEqualTo("[?(@['name'] =~ /.*?/i)]"); assertThat(compile("[?(@.name =~ /.*?/i)]").toString()).isEqualTo("[?(@['name'] =~ /.*?/i)]");
assertThat(compile("[?(@.name =~ /.*?/)]").toString()).isEqualTo("[?(@['name'] =~ /.*?/)]"); assertThat(compile("[?(@.name =~ /.*?/)]").toString()).isEqualTo("[?(@['name'] =~ /.*?/)]");
assertThat(compile("[?($[\"firstname\"][\"lastname\"])]").toString()).isEqualTo("[?($['firstname']['lastname'])]"); assertThat(compile("[?($[\"firstname\"][\"lastname\"])]").toString()).isEqualTo("[?($[\"firstname\"][\"lastname\"])]");
assertThat(compile("[?($[\"firstname\"].lastname)]").toString()).isEqualTo("[?($['firstname']['lastname'])]"); assertThat(compile("[?($[\"firstname\"].lastname)]").toString()).isEqualTo("[?($[\"firstname\"]['lastname'])]");
assertThat(compile("[?($[\"firstname\", \"lastname\"])]").toString()).isEqualTo("[?($['firstname','lastname'])]"); assertThat(compile("[?($[\"firstname\", \"lastname\"])]").toString()).isEqualTo("[?($[\"firstname\",\"lastname\"])]");
} }
@Test @Test
public void string_quoute_style_is_serialized() { public void string_quote_style_is_serialized() {
assertThat(compile("[?('apa' == 'apa')]").toString()).isEqualTo("[?('apa' == 'apa')]"); assertThat(compile("[?('apa' == 'apa')]").toString()).isEqualTo("[?('apa' == 'apa')]");
assertThat(compile("[?('apa' == \"apa\")]").toString()).isEqualTo("[?('apa' == \"apa\")]"); assertThat(compile("[?('apa' == \"apa\")]").toString()).isEqualTo("[?('apa' == \"apa\")]");
} }
@Test
public void string_can_contain_path_chars() {
assertThat(compile("[?(@[')]@$)]'] == ')]@$)]')]").toString()).isEqualTo("[?(@[')]@$)]'] == ')]@$)]')]");
assertThat(compile("[?(@[\")]@$)]\"] == \")]@$)]\")]").toString()).isEqualTo("[?(@[\")]@$)]\"] == \")]@$)]\")]");
}
@Test @Test
public void invalid_filters_does_not_compile() { public void invalid_filters_does_not_compile() {

2
json-path/src/test/java/com/jayway/jsonpath/PathCompilerTest.java

@ -59,7 +59,7 @@ public class PathCompilerTest {
assertThat(compile("$['1prop']").toString()).isEqualTo("$['1prop']"); assertThat(compile("$['1prop']").toString()).isEqualTo("$['1prop']");
assertThat(compile("$['@prop']").toString()).isEqualTo("$['@prop']"); assertThat(compile("$['@prop']").toString()).isEqualTo("$['@prop']");
assertThat(compile("$[ '@prop' ]").toString()).isEqualTo("$['@prop']"); assertThat(compile("$[ '@prop' ]").toString()).isEqualTo("$['@prop']");
assertThat(compile("$[\"prop\"]").toString()).isEqualTo("$['prop']"); assertThat(compile("$[\"prop\"]").toString()).isEqualTo("$[\"prop\"]");
} }
@Test @Test

2
json-path/src/test/java/com/jayway/jsonpath/internal/path/PathTokenTest.java

@ -33,7 +33,7 @@ public class PathTokenTest extends BaseTest {
private PathToken makePPT(final String ... properties) { private PathToken makePPT(final String ... properties) {
return new PropertyPathToken(Arrays.asList(properties)); return new PropertyPathToken(Arrays.asList(properties), '\'');
} }
private PathToken makePathReturningTail(final PathToken ... tokens) { private PathToken makePathReturningTail(final PathToken ... tokens) {

Loading…
Cancel
Save