8 changed files with 3975 additions and 1 deletions
@ -0,0 +1,90 @@ |
|||||||
|
package com.jayway.jsonpath.internal.path; |
||||||
|
|
||||||
|
import com.jayway.jsonpath.internal.PathRef; |
||||||
|
import com.jayway.jsonpath.internal.Utils; |
||||||
|
import com.jayway.jsonpath.spi.json.JsonProvider; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Collections; |
||||||
|
import java.util.List; |
||||||
|
import java.util.StringTokenizer; |
||||||
|
|
||||||
|
public class CaretPathToken extends PathToken { |
||||||
|
|
||||||
|
public final static char SINGLE_QUOTE = '\''; |
||||||
|
public final static char CARET = '^'; |
||||||
|
|
||||||
|
@Override |
||||||
|
public void evaluate(String currentPath, PathRef parent, Object model, EvaluationContextImpl ctx) { |
||||||
|
if ( isRoot() ) return; |
||||||
|
String evalPath = Utils.concat(currentPath, getPathFragment()); |
||||||
|
Object p = getParentModel(currentPath, model, ctx); |
||||||
|
if ( p == null ) return; |
||||||
|
PathRef pathRef = ctx.forUpdate() ? parent : PathRef.NO_OP; |
||||||
|
if ( isLeaf() ) { |
||||||
|
ctx.addResult(evalPath, pathRef, p); |
||||||
|
} else { |
||||||
|
next().evaluate(evalPath, pathRef, p, ctx); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private Object getParentModel(final String path, final Object model, final EvaluationContextImpl ctx) { |
||||||
|
Object root = ctx.rootDocument(); |
||||||
|
List list = tokenizePath(path); |
||||||
|
list = list.subList(0, list.size() - getParentDepth(path)); |
||||||
|
Object p = root; |
||||||
|
Object last = null; |
||||||
|
for ( Object o : list ) { |
||||||
|
last = p; |
||||||
|
p = searchObject(o, p, ctx); |
||||||
|
} |
||||||
|
return p; |
||||||
|
} |
||||||
|
private int getParentDepth(final String path) { |
||||||
|
int i = 0; |
||||||
|
while ( true ) { |
||||||
|
if ( path.charAt(path.length() - 1 - i) == CARET ) { |
||||||
|
i++; |
||||||
|
} else { |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
return i; |
||||||
|
} |
||||||
|
|
||||||
|
private Object searchObject(Object key, Object o, final EvaluationContextImpl ctx) { |
||||||
|
if ( key instanceof String ) { |
||||||
|
return ctx.jsonProvider().getMapValue(o, (String)key); |
||||||
|
} else if ( key instanceof Integer ) { |
||||||
|
return ctx.jsonProvider().getArrayIndex(o, (Integer)key); |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
private List<Object> tokenizePath(final String path) { |
||||||
|
StringTokenizer st = new StringTokenizer(path, "$[]^"); |
||||||
|
List obj = new ArrayList(); |
||||||
|
while ( st.hasMoreTokens() ) { |
||||||
|
String token = st.nextToken().trim(); |
||||||
|
if ( token.indexOf(SINGLE_QUOTE) == 0 ) { |
||||||
|
obj.add(token.substring(1, token.length() - 1)); |
||||||
|
} else { |
||||||
|
try { |
||||||
|
obj.add(Integer.parseInt(token)); |
||||||
|
} catch ( NumberFormatException ex) { |
||||||
|
; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return obj; |
||||||
|
} |
||||||
|
@Override |
||||||
|
public boolean isTokenDefinite() { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String getPathFragment() { |
||||||
|
return "^"; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,44 @@ |
|||||||
|
package com.jayway.jsonpath; |
||||||
|
|
||||||
|
import org.junit.Assert; |
||||||
|
import org.junit.Test; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.io.InputStream; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.LinkedList; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
import static com.jayway.jsonpath.JsonPath.parse; |
||||||
|
import static com.jayway.jsonpath.JsonPath.read; |
||||||
|
import static java.util.Collections.emptyMap; |
||||||
|
import static org.assertj.core.api.Assertions.assertThat; |
||||||
|
|
||||||
|
public class CaretTest extends BaseTest { |
||||||
|
|
||||||
|
private static final Map<String, Object> EMPTY_MAP = emptyMap(); |
||||||
|
|
||||||
|
|
||||||
|
@Test |
||||||
|
public void get_parent_node() { |
||||||
|
|
||||||
|
try(InputStream is = this.getClass().getResourceAsStream("/issue_caret.json")) { |
||||||
|
Object result = read(is, "$..ExtendedResult[?(@.:Type =='ER' && @.:Code == 'FX')].Extension[?(@.:Code == 'PENALTY' && @.:Value)]^^^^^^[':SortOrder']"); |
||||||
|
System.out.println(result.toString()); |
||||||
|
} catch ( IOException ioex) { |
||||||
|
ioex.printStackTrace(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
// Helper converter implementation for test cases.
|
||||||
|
private class ToStringMapFunction implements MapFunction { |
||||||
|
|
||||||
|
@Override |
||||||
|
public Object map(Object currentValue, Configuration configuration) { |
||||||
|
return currentValue.toString()+"converted"; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue