kalle
13 years ago
15 changed files with 825 additions and 7 deletions
@ -1,5 +1,4 @@ |
|||||||
Java DSL for reading and testing JSON documents. |
Java DSL for reading and testing JSON documents. |
||||||
|
|
||||||
|
COPY DEPENDENCIES : mvn clean compile dependency:copy-dependencies -DstripVersion |
||||||
|
FONT LOGO : Santa Fe LET 50 |
||||||
Santa Fe LET 50 |
|
@ -0,0 +1,23 @@ |
|||||||
|
package com.jayway.jsonpath.reader; |
||||||
|
|
||||||
|
import com.jayway.jsonpath.reader.filter.Filter; |
||||||
|
import com.jayway.jsonpath.reader.filter.FilterFactory; |
||||||
|
|
||||||
|
/** |
||||||
|
* Created by IntelliJ IDEA. |
||||||
|
* User: kallestenflo |
||||||
|
* Date: 11/4/11 |
||||||
|
* Time: 10:00 PM |
||||||
|
*/ |
||||||
|
public class PathToken { |
||||||
|
|
||||||
|
private Filter filter; |
||||||
|
|
||||||
|
public PathToken(String pathFragment) { |
||||||
|
filter = FilterFactory.createFilter(pathFragment); |
||||||
|
} |
||||||
|
|
||||||
|
public Object filter(Object model){ |
||||||
|
return filter.filter(model); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,210 @@ |
|||||||
|
package com.jayway.jsonpath.reader; |
||||||
|
|
||||||
|
import com.jayway.jsonpath.InvalidPathException; |
||||||
|
|
||||||
|
import java.util.Iterator; |
||||||
|
import java.util.LinkedList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* Created by IntelliJ IDEA. |
||||||
|
* User: kallestenflo |
||||||
|
* Date: 11/4/11 |
||||||
|
* Time: 9:53 PM |
||||||
|
*/ |
||||||
|
public class PathTokenizer implements Iterable<PathToken> { |
||||||
|
|
||||||
|
private char[] pathChars; |
||||||
|
private int index = 0; |
||||||
|
private List<PathToken> pathTokens = new LinkedList<PathToken>(); |
||||||
|
|
||||||
|
public PathTokenizer(String jsonPath) { |
||||||
|
|
||||||
|
if (!jsonPath.startsWith("$") && !jsonPath.startsWith("$[")) { |
||||||
|
jsonPath = "$." + jsonPath; |
||||||
|
} |
||||||
|
pathChars = jsonPath.toCharArray(); |
||||||
|
|
||||||
|
for (String pathFragment : splitPath()) { |
||||||
|
pathTokens.add(new PathToken(pathFragment)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public Iterator<PathToken> iterator() { |
||||||
|
return pathTokens.iterator(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------
|
||||||
|
//
|
||||||
|
// Split path
|
||||||
|
//
|
||||||
|
//--------------------------------------------
|
||||||
|
private boolean isEmpty() { |
||||||
|
return index == pathChars.length; |
||||||
|
} |
||||||
|
|
||||||
|
private char peek() { |
||||||
|
return pathChars[index]; |
||||||
|
} |
||||||
|
|
||||||
|
private char poll() { |
||||||
|
char peek = peek(); |
||||||
|
index++; |
||||||
|
return peek; |
||||||
|
} |
||||||
|
|
||||||
|
public List<String> splitPath() { |
||||||
|
|
||||||
|
List<String> fragments = new LinkedList<String>(); |
||||||
|
while (!isEmpty()) { |
||||||
|
skip(' '); |
||||||
|
char current = peek(); |
||||||
|
|
||||||
|
switch (current) { |
||||||
|
case '$': |
||||||
|
fragments.add(Character.toString(current)); |
||||||
|
poll(); |
||||||
|
break; |
||||||
|
|
||||||
|
case '.': |
||||||
|
poll(); |
||||||
|
if (peek() == '.') { |
||||||
|
poll(); |
||||||
|
fragments.add(".."); |
||||||
|
|
||||||
|
assertNotInvalidPeek('.'); |
||||||
|
} |
||||||
|
break; |
||||||
|
|
||||||
|
case '[': |
||||||
|
fragments.add(extract(true, ']')); |
||||||
|
break; |
||||||
|
|
||||||
|
default: |
||||||
|
fragments.add(extract(false, '[', '.')); |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
return fragments; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private String extract(boolean includeSopChar, char... stopChars) { |
||||||
|
StringBuilder sb = new StringBuilder(); |
||||||
|
while (!isEmpty() && (!isStopChar(peek(), stopChars))) { |
||||||
|
|
||||||
|
char c = poll(); |
||||||
|
|
||||||
|
if (isStopChar(c, stopChars)) { |
||||||
|
if (includeSopChar) { |
||||||
|
sb.append(c); |
||||||
|
} |
||||||
|
} else { |
||||||
|
sb.append(c); |
||||||
|
} |
||||||
|
} |
||||||
|
if (includeSopChar) { |
||||||
|
assertValidPeek(false, stopChars); |
||||||
|
sb.append(poll()); |
||||||
|
} else { |
||||||
|
assertValidPeek(true, stopChars); |
||||||
|
} |
||||||
|
return clean(sb); |
||||||
|
} |
||||||
|
|
||||||
|
private String clean(StringBuilder sb) { |
||||||
|
|
||||||
|
String src = sb.toString(); |
||||||
|
|
||||||
|
src = trim(src, "'"); |
||||||
|
src = trim(src, ")"); |
||||||
|
src = trim(src, "("); |
||||||
|
src = trimLeft(src, "?"); |
||||||
|
src = trimLeft(src, "@"); |
||||||
|
|
||||||
|
if (src.length() > 5 && src.subSequence(0, 2).equals("['")) { |
||||||
|
src = src.substring(2); |
||||||
|
src = src.substring(0, src.length() - 2); |
||||||
|
} |
||||||
|
|
||||||
|
return src.trim(); |
||||||
|
} |
||||||
|
|
||||||
|
private String trim(String src, String trim) { |
||||||
|
return trimLeft(trimRight(src, trim), trim); |
||||||
|
} |
||||||
|
|
||||||
|
private String trimRight(String src, String trim) { |
||||||
|
String scanFor = trim + " "; |
||||||
|
if (src.contains(scanFor)) { |
||||||
|
while (src.contains(scanFor)) { |
||||||
|
src = src.replace(scanFor, trim); |
||||||
|
} |
||||||
|
} |
||||||
|
return src; |
||||||
|
} |
||||||
|
|
||||||
|
private String trimLeft(String src, String trim) { |
||||||
|
String scanFor = " " + trim; |
||||||
|
if (src.contains(scanFor)) { |
||||||
|
while (src.contains(scanFor)) { |
||||||
|
src = src.replace(scanFor, trim); |
||||||
|
} |
||||||
|
} |
||||||
|
return src; |
||||||
|
} |
||||||
|
|
||||||
|
private boolean isStopChar(char c, char... scanFor) { |
||||||
|
boolean found = false; |
||||||
|
for (char check : scanFor) { |
||||||
|
if (check == c) { |
||||||
|
found = true; |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
return found; |
||||||
|
} |
||||||
|
|
||||||
|
private void skip(char target) { |
||||||
|
if (isEmpty()) { |
||||||
|
return; |
||||||
|
} |
||||||
|
while (pathChars[index] == target) { |
||||||
|
index++; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private void assertNotInvalidPeek(char... invalidChars) { |
||||||
|
if (isEmpty()) { |
||||||
|
return; |
||||||
|
} |
||||||
|
char peek = peek(); |
||||||
|
for (char check : invalidChars) { |
||||||
|
if (check == peek) { |
||||||
|
throw new InvalidPathException("Char: " + peek + " at current position is not valid!"); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private void assertValidPeek(boolean acceptEmpty, char... validChars) { |
||||||
|
if (isEmpty() && acceptEmpty) { |
||||||
|
return; |
||||||
|
} |
||||||
|
if (isEmpty()) { |
||||||
|
throw new InvalidPathException("Path is incomplete"); |
||||||
|
} |
||||||
|
boolean found = false; |
||||||
|
char peek = peek(); |
||||||
|
for (char check : validChars) { |
||||||
|
if (check == peek) { |
||||||
|
found = true; |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
if (!found) { |
||||||
|
throw new InvalidPathException("Path is invalid"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,100 @@ |
|||||||
|
package com.jayway.jsonpath.reader.filter; |
||||||
|
|
||||||
|
import com.jayway.jsonpath.InvalidPathException; |
||||||
|
import com.jayway.jsonpath.eval.ExpressionEvaluator; |
||||||
|
|
||||||
|
import java.util.LinkedList; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.regex.Matcher; |
||||||
|
import java.util.regex.Pattern; |
||||||
|
|
||||||
|
/** |
||||||
|
* Created by IntelliJ IDEA. |
||||||
|
* User: kallestenflo |
||||||
|
* Date: 11/5/11 |
||||||
|
* Time: 12:35 AM |
||||||
|
*/ |
||||||
|
public class ArrayEvalFilter extends Filter { |
||||||
|
|
||||||
|
public static final Pattern PATTERN = Pattern.compile("(.*?)\\s?([=<>]+)\\s?(.*)"); |
||||||
|
|
||||||
|
public ArrayEvalFilter(String condition) { |
||||||
|
super(condition); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Object filter(Object obj) { |
||||||
|
//[?(@.isbn = 10)]
|
||||||
|
List<Object> src = toList(obj); |
||||||
|
List<Object> result = new LinkedList<Object>(); |
||||||
|
|
||||||
|
String trimmedCondition = trim(condition, 5, 2); |
||||||
|
|
||||||
|
ConditionStatement conditionStatement = createConditionStatement(trimmedCondition); |
||||||
|
|
||||||
|
|
||||||
|
for (Object item : src) { |
||||||
|
if (isMatch(item, conditionStatement)) { |
||||||
|
result.add(item); |
||||||
|
} |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
private boolean isMatch(Object check, ConditionStatement conditionStatement) { |
||||||
|
if (!isMap(check)) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
Map obj = toMap(check); |
||||||
|
|
||||||
|
if (!obj.containsKey(conditionStatement.getField())) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
Object propertyValue = obj.get(conditionStatement.getField()); |
||||||
|
|
||||||
|
if (isContainer(propertyValue)) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
return ExpressionEvaluator.eval(propertyValue, conditionStatement.getOperator(), conditionStatement.getExpected()); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private ConditionStatement createConditionStatement(String str) { |
||||||
|
Matcher matcher = PATTERN.matcher(str); |
||||||
|
if (matcher.matches()) { |
||||||
|
String property = matcher.group(1); |
||||||
|
String operator = matcher.group(2); |
||||||
|
String expected = matcher.group(3); |
||||||
|
|
||||||
|
return new ConditionStatement(property, operator, expected); |
||||||
|
} else { |
||||||
|
throw new InvalidPathException("Invalid match " + str); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private class ConditionStatement { |
||||||
|
private String field; |
||||||
|
private String operator; |
||||||
|
private String expected; |
||||||
|
|
||||||
|
private ConditionStatement(String field, String operator, String expected) { |
||||||
|
this.field = field; |
||||||
|
this.operator = operator; |
||||||
|
this.expected = expected; |
||||||
|
} |
||||||
|
|
||||||
|
public String getField() { |
||||||
|
return field; |
||||||
|
} |
||||||
|
|
||||||
|
public String getOperator() { |
||||||
|
return operator; |
||||||
|
} |
||||||
|
|
||||||
|
public String getExpected() { |
||||||
|
return expected; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,52 @@ |
|||||||
|
package com.jayway.jsonpath.reader.filter; |
||||||
|
|
||||||
|
import java.util.LinkedList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* Created by IntelliJ IDEA. |
||||||
|
* User: kallestenflo |
||||||
|
* Date: 11/4/11 |
||||||
|
* Time: 11:25 PM |
||||||
|
*/ |
||||||
|
public class ArrayIndexFilter extends Filter { |
||||||
|
public ArrayIndexFilter(String condition) { |
||||||
|
super(condition); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Object filter(Object obj) { |
||||||
|
|
||||||
|
List<Object> src = toList(obj); |
||||||
|
List<Object> result = new LinkedList<Object>(); |
||||||
|
|
||||||
|
String trimmedCondition = trim(condition, 1, 1); |
||||||
|
|
||||||
|
if (trimmedCondition.startsWith(":")) { |
||||||
|
trimmedCondition = trim(trimmedCondition, 1, 0); |
||||||
|
int get = Integer.parseInt(trimmedCondition); |
||||||
|
for (int i = 0; i < get; i++) { |
||||||
|
result.add(src.get(i)); |
||||||
|
} |
||||||
|
return result; |
||||||
|
|
||||||
|
} else if (trimmedCondition.endsWith(":")) { |
||||||
|
trimmedCondition = trim(trimmedCondition, 1, 1); |
||||||
|
int get = Integer.parseInt(trimmedCondition); |
||||||
|
return src.get(src.size() - get); |
||||||
|
} else { |
||||||
|
String[] indexArr = trimmedCondition.split(","); |
||||||
|
|
||||||
|
if (indexArr.length == 1) { |
||||||
|
|
||||||
|
return src.get(Integer.parseInt(indexArr[0])); |
||||||
|
|
||||||
|
} else { |
||||||
|
for (String idx : indexArr) { |
||||||
|
result.add(src.get(Integer.parseInt(idx.trim()))); |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,30 @@ |
|||||||
|
package com.jayway.jsonpath.reader.filter; |
||||||
|
|
||||||
|
import java.util.LinkedList; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
/** |
||||||
|
* Created by IntelliJ IDEA. |
||||||
|
* User: kallestenflo |
||||||
|
* Date: 11/4/11 |
||||||
|
* Time: 10:17 PM |
||||||
|
*/ |
||||||
|
public class FieldFilter extends Filter { |
||||||
|
|
||||||
|
public FieldFilter(String condition) { |
||||||
|
super(condition); |
||||||
|
} |
||||||
|
|
||||||
|
public Object filter(Object obj) { |
||||||
|
if(isList(obj)){ |
||||||
|
List<Object> result = new LinkedList<Object>(); |
||||||
|
for (Object item : toList(obj)) { |
||||||
|
result.add(filter(item)); |
||||||
|
} |
||||||
|
return result; |
||||||
|
} else { |
||||||
|
return getMapValue(obj, condition); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,77 @@ |
|||||||
|
package com.jayway.jsonpath.reader.filter; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
/** |
||||||
|
* Created by IntelliJ IDEA. |
||||||
|
* User: kallestenflo |
||||||
|
* Date: 11/4/11 |
||||||
|
* Time: 10:14 PM |
||||||
|
*/ |
||||||
|
public abstract class Filter { |
||||||
|
|
||||||
|
protected final String condition; |
||||||
|
|
||||||
|
public Filter(String condition) { |
||||||
|
this.condition = condition; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* checks if object is <code>instanceof</code> <code>java.util.List</code> or <code>java.util.Map</code> |
||||||
|
* |
||||||
|
* @param obj object to check |
||||||
|
* @return true if List or Map |
||||||
|
*/ |
||||||
|
protected boolean isContainer(Object obj) { |
||||||
|
return (isList(obj) || isMap(obj)); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* checks if object is <code>instanceof</code> <code>java.util.List</code> |
||||||
|
* |
||||||
|
* @param obj object to check |
||||||
|
* @return true if List |
||||||
|
*/ |
||||||
|
protected boolean isList(Object obj) { |
||||||
|
return (obj instanceof List); |
||||||
|
} |
||||||
|
|
||||||
|
protected List<Object> toList(Object list) { |
||||||
|
return (List<Object>) list; |
||||||
|
} |
||||||
|
|
||||||
|
protected Map<String, Object> toMap(Object map) { |
||||||
|
return (Map<String, Object>) map; |
||||||
|
} |
||||||
|
|
||||||
|
protected Object getMapValue(Object obj, String key) { |
||||||
|
Map<String, Object> map = toMap(obj); |
||||||
|
return map.get(key); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* checks if object is <code>instanceof</code> <code>java.util.Map</code> |
||||||
|
* |
||||||
|
* @param obj object to check |
||||||
|
* @return true if Map |
||||||
|
*/ |
||||||
|
protected boolean isMap(Object obj) { |
||||||
|
return (obj instanceof Map); |
||||||
|
} |
||||||
|
|
||||||
|
protected String trim(String str, int front, int end) { |
||||||
|
String res = str; |
||||||
|
|
||||||
|
if (front > 0) { |
||||||
|
res = str.substring(front); |
||||||
|
} |
||||||
|
if (end > 0) { |
||||||
|
res = res.substring(0, res.length() - end); |
||||||
|
} |
||||||
|
return res; |
||||||
|
} |
||||||
|
|
||||||
|
public abstract Object filter(Object obj); |
||||||
|
|
||||||
|
} |
@ -0,0 +1,52 @@ |
|||||||
|
package com.jayway.jsonpath.reader.filter; |
||||||
|
|
||||||
|
import com.jayway.jsonpath.filter.ListEvalFilter; |
||||||
|
|
||||||
|
/** |
||||||
|
* Created by IntelliJ IDEA. |
||||||
|
* User: kallestenflo |
||||||
|
* Date: 11/4/11 |
||||||
|
* Time: 10:13 PM |
||||||
|
*/ |
||||||
|
public class FilterFactory { |
||||||
|
|
||||||
|
public static Filter createFilter(String pathFragment) { |
||||||
|
|
||||||
|
if ("$".equals(pathFragment) || "*".equals(pathFragment) || "[*]".equals(pathFragment)) { |
||||||
|
|
||||||
|
return new PassThrewFilter(pathFragment); |
||||||
|
|
||||||
|
} else if (pathFragment.contains("..")) { |
||||||
|
|
||||||
|
return new ScanFilter(pathFragment); |
||||||
|
|
||||||
|
} else if (!pathFragment.contains("[")) { |
||||||
|
|
||||||
|
return new FieldFilter(pathFragment); |
||||||
|
|
||||||
|
} else if (pathFragment.contains("[")) { |
||||||
|
|
||||||
|
if (pathFragment.startsWith("[?")) { |
||||||
|
if(!pathFragment.contains("=")){ |
||||||
|
//[?(@.isbn)]
|
||||||
|
return new HasFieldFilter(pathFragment); |
||||||
|
} else { |
||||||
|
//[?(@.name='foo')]
|
||||||
|
return new ArrayEvalFilter(pathFragment); |
||||||
|
} |
||||||
|
} else { |
||||||
|
//[0]
|
||||||
|
//[0,1, ...]
|
||||||
|
//[-1:]
|
||||||
|
//[:1]
|
||||||
|
return new ArrayIndexFilter(pathFragment); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
throw new UnsupportedOperationException(".."); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} |
@ -0,0 +1,38 @@ |
|||||||
|
package com.jayway.jsonpath.reader.filter; |
||||||
|
|
||||||
|
import java.util.LinkedList; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
/** |
||||||
|
* Created by IntelliJ IDEA. |
||||||
|
* User: kallestenflo |
||||||
|
* Date: 11/5/11 |
||||||
|
* Time: 12:17 AM |
||||||
|
*/ |
||||||
|
public class HasFieldFilter extends Filter { |
||||||
|
|
||||||
|
public HasFieldFilter(String condition) { |
||||||
|
super(condition); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Object filter(Object obj) { |
||||||
|
|
||||||
|
//[?(@.isbn)]
|
||||||
|
List<Object> src = toList(obj); |
||||||
|
List<Object> result = new LinkedList<Object>(); |
||||||
|
|
||||||
|
String trimmedCondition = trim(condition, 5, 2); |
||||||
|
|
||||||
|
for (Object item : src) { |
||||||
|
if(isMap(item)){ |
||||||
|
Map<String, Object> map = toMap(item); |
||||||
|
if(map.containsKey(trimmedCondition)){ |
||||||
|
result.add(map); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,18 @@ |
|||||||
|
package com.jayway.jsonpath.reader.filter; |
||||||
|
|
||||||
|
/** |
||||||
|
* Created by IntelliJ IDEA. |
||||||
|
* User: kallestenflo |
||||||
|
* Date: 11/4/11 |
||||||
|
* Time: 10:15 PM |
||||||
|
*/ |
||||||
|
public class PassThrewFilter extends Filter { |
||||||
|
|
||||||
|
public PassThrewFilter(String condition) { |
||||||
|
super(condition); |
||||||
|
} |
||||||
|
|
||||||
|
public Object filter(Object obj) { |
||||||
|
return obj; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,48 @@ |
|||||||
|
package com.jayway.jsonpath.reader.filter; |
||||||
|
|
||||||
|
import com.jayway.jsonpath.JsonUtil; |
||||||
|
|
||||||
|
import java.util.LinkedList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* Created by IntelliJ IDEA. |
||||||
|
* User: kallestenflo |
||||||
|
* Date: 11/7/11 |
||||||
|
* Time: 12:31 PM |
||||||
|
*/ |
||||||
|
public class ScanFilter extends Filter { |
||||||
|
|
||||||
|
public ScanFilter(String condition) { |
||||||
|
super(condition); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Object filter(Object obj) { |
||||||
|
List<Object> result = new LinkedList<Object>(); |
||||||
|
scan(obj, result); |
||||||
|
|
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private void scan(Object container, List<Object> result) { |
||||||
|
|
||||||
|
if (isMap(container)) { |
||||||
|
result.add(container); |
||||||
|
|
||||||
|
for (Object value : toMap(container).values()) { |
||||||
|
if (isContainer(value)) { |
||||||
|
scan(value, result); |
||||||
|
} |
||||||
|
} |
||||||
|
} else if (isList(container)) { |
||||||
|
|
||||||
|
for (Object value : JsonUtil.toList(container)) { |
||||||
|
if (isContainer(value)) { |
||||||
|
scan(value, result); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,167 @@ |
|||||||
|
package com.jayway.jsonpath; |
||||||
|
|
||||||
|
import com.jayway.jsonpath.reader.PathToken; |
||||||
|
import com.jayway.jsonpath.reader.PathTokenizer; |
||||||
|
import org.junit.Test; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import static junit.framework.Assert.assertEquals; |
||||||
|
import static org.hamcrest.Matchers.hasItems; |
||||||
|
import static org.junit.Assert.assertThat; |
||||||
|
|
||||||
|
/** |
||||||
|
* Created by IntelliJ IDEA. |
||||||
|
* User: kallestenflo |
||||||
|
* Date: 11/4/11 |
||||||
|
* Time: 10:44 PM |
||||||
|
*/ |
||||||
|
public class PathTokenizerTest { |
||||||
|
|
||||||
|
public final static String DOCUMENT = |
||||||
|
"{ \"store\": {\n" + |
||||||
|
" \"book\": [ \n" + |
||||||
|
" { \"category\": \"reference\",\n" + |
||||||
|
" \"author\": \"Nigel Rees\",\n" + |
||||||
|
" \"title\": \"Sayings of the Century\",\n" + |
||||||
|
" \"price\": 8.95\n" + |
||||||
|
" },\n" + |
||||||
|
" { \"category\": \"fiction\",\n" + |
||||||
|
" \"author\": \"Evelyn Waugh\",\n" + |
||||||
|
" \"title\": \"Sword of Honour\",\n" + |
||||||
|
" \"price\": 12.99\n" + |
||||||
|
" },\n" + |
||||||
|
" { \"category\": \"fiction\",\n" + |
||||||
|
" \"author\": \"Herman Melville\",\n" + |
||||||
|
" \"title\": \"Moby Dick\",\n" + |
||||||
|
" \"isbn\": \"0-553-21311-3\",\n" + |
||||||
|
" \"price\": 8.99\n" + |
||||||
|
" },\n" + |
||||||
|
" { \"category\": \"fiction\",\n" + |
||||||
|
" \"author\": \"J. R. R. Tolkien\",\n" + |
||||||
|
" \"title\": \"The Lord of the Rings\",\n" + |
||||||
|
" \"custom\": \"onely this\",\n" + |
||||||
|
" \"isbn\": \"0-395-19395-8\",\n" + |
||||||
|
" \"price\": 22.99\n" + |
||||||
|
" }\n" + |
||||||
|
" ],\n" + |
||||||
|
" \"bicycle\": {\n" + |
||||||
|
" \"color\": \"red\",\n" + |
||||||
|
" \"price\": 19.95,\n" + |
||||||
|
" \"foo:bar\": \"fooBar\",\n" + |
||||||
|
" \"dot.notation\": \"new\"\n" + |
||||||
|
" }\n" + |
||||||
|
" }\n" + |
||||||
|
"}"; |
||||||
|
|
||||||
|
@Test |
||||||
|
public void path_tokens_can_be_read() throws Exception { |
||||||
|
Object result = JsonPath.parse(DOCUMENT); |
||||||
|
|
||||||
|
for (PathToken pathToken : new PathTokenizer("$.store.bicycle.color")) { |
||||||
|
result = pathToken.filter(result); |
||||||
|
} |
||||||
|
|
||||||
|
assertEquals("red", result); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void read_an_array_without_filters() throws Exception { |
||||||
|
Object result = JsonPath.parse(DOCUMENT); |
||||||
|
|
||||||
|
for (PathToken pathToken : new PathTokenizer("$.store.book")) { |
||||||
|
result = pathToken.filter(result); |
||||||
|
} |
||||||
|
|
||||||
|
assertEquals(4, toList(result).size()); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void read_a_literal_property_from_object_in_array() throws Exception { |
||||||
|
Object result = JsonPath.parse(DOCUMENT); |
||||||
|
|
||||||
|
for (PathToken pathToken : new PathTokenizer("$.store.book[*].title")) { |
||||||
|
result = pathToken.filter(result); |
||||||
|
} |
||||||
|
|
||||||
|
assertEquals(4, toList(result).size()); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void read_a_literal_property_from_position_in_array() throws Exception { |
||||||
|
Object result = JsonPath.parse(DOCUMENT); |
||||||
|
|
||||||
|
for (PathToken pathToken : new PathTokenizer("$.store.book[0].title")) { |
||||||
|
result = pathToken.filter(result); |
||||||
|
} |
||||||
|
|
||||||
|
assertEquals("Sayings of the Century", result); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void read_a_literal_property_from_two_positions_in_array() throws Exception { |
||||||
|
Object result = JsonPath.parse(DOCUMENT); |
||||||
|
|
||||||
|
for (PathToken pathToken : new PathTokenizer("$.store.book[0, 1].author")) { |
||||||
|
result = pathToken.filter(result); |
||||||
|
} |
||||||
|
|
||||||
|
assertThat(this.<String>toList(result), hasItems("Nigel Rees", "Evelyn Waugh")); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void read_a_literal_property_from_head_in_array() throws Exception { |
||||||
|
Object result = JsonPath.parse(DOCUMENT); |
||||||
|
|
||||||
|
for (PathToken pathToken : new PathTokenizer("$.store.book[:2].author")) { |
||||||
|
result = pathToken.filter(result); |
||||||
|
} |
||||||
|
|
||||||
|
assertThat(this.<String>toList(result), hasItems("Nigel Rees", "Evelyn Waugh")); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void read_a_literal_property_from_tail_in_array() throws Exception { |
||||||
|
Object result = JsonPath.parse(DOCUMENT); |
||||||
|
|
||||||
|
for (PathToken pathToken : new PathTokenizer("$.store.book[-1:].author")) { |
||||||
|
result = pathToken.filter(result); |
||||||
|
} |
||||||
|
assertEquals("J. R. R. Tolkien", result); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void field_defined_in_array_object() throws Exception { |
||||||
|
Object result = JsonPath.parse(DOCUMENT); |
||||||
|
|
||||||
|
for (PathToken pathToken : new PathTokenizer("$.store.book[?(@.custom)].author")) { |
||||||
|
result = pathToken.filter(result); |
||||||
|
} |
||||||
|
assertThat(this.<String>toList(result), hasItems("J. R. R. Tolkien")); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void property_value_in_array_object() throws Exception { |
||||||
|
Object result = JsonPath.parse(DOCUMENT); |
||||||
|
|
||||||
|
for (PathToken pathToken : new PathTokenizer("$.store.book[?(@.custom = 'onely this')].author")) { |
||||||
|
result = pathToken.filter(result); |
||||||
|
} |
||||||
|
assertThat(this.<String>toList(result), hasItems("J. R. R. Tolkien")); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void deep_scan() throws Exception { |
||||||
|
Object result = JsonPath.parse(DOCUMENT); |
||||||
|
|
||||||
|
for (PathToken pathToken : new PathTokenizer("$..author")) { |
||||||
|
result = pathToken.filter(result); |
||||||
|
} |
||||||
|
assertThat(this.<String>toList(result), hasItems("Nigel Rees","Evelyn Waugh", "J. R. R. Tolkien")); |
||||||
|
} |
||||||
|
|
||||||
|
private <T> List<T> toList(Object obj) { |
||||||
|
return (List<T>) obj; |
||||||
|
} |
||||||
|
|
||||||
|
} |
Loading…
Reference in new issue