Browse Source

merge JsonProvider's getMapValue methods, various small performance improvements

pull/47/head
Jochen Berger 10 years ago
parent
commit
2664f83104
  1. 6
      json-path/src/main/java/com/jayway/jsonpath/internal/compiler/PathToken.java
  2. 114
      json-path/src/main/java/com/jayway/jsonpath/internal/compiler/ScanPathToken.java
  3. 16
      json-path/src/main/java/com/jayway/jsonpath/internal/spi/json/AbstractJsonProvider.java
  4. 12
      json-path/src/main/java/com/jayway/jsonpath/spi/json/JsonProvider.java

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

@ -69,12 +69,12 @@ public abstract class PathToken {
} }
} }
private boolean hasProperty(String property, Object model, EvaluationContextImpl ctx) { private static boolean hasProperty(String property, Object model, EvaluationContextImpl ctx) {
return ctx.jsonProvider().getPropertyKeys(model).contains(property); return ctx.jsonProvider().getPropertyKeys(model).contains(property);
} }
private Object readObjectProperty(String property, Object model, EvaluationContextImpl ctx) { private static Object readObjectProperty(String property, Object model, EvaluationContextImpl ctx) {
return ctx.jsonProvider().getMapValue(model, property, true); return ctx.jsonProvider().getMapValue(model, property);
} }
void handleArrayIndex(int index, String currentPath, Object json, EvaluationContextImpl ctx) { void handleArrayIndex(int index, String currentPath, Object json, EvaluationContextImpl ctx) {

114
json-path/src/main/java/com/jayway/jsonpath/internal/compiler/ScanPathToken.java

@ -4,6 +4,8 @@ import java.util.Collection;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import com.jayway.jsonpath.spi.json.JsonProvider;
/** /**
* *
*/ */
@ -39,7 +41,7 @@ public class ScanPathToken extends PathToken {
} }
} }
public void walk(String currentPath, Object model, EvaluationContextImpl ctx, Predicate predicate, Map<String, Object> predicateMatches) { public static void walk(String currentPath, Object model, EvaluationContextImpl ctx, Predicate predicate, Map<String, Object> predicateMatches) {
if (ctx.jsonProvider().isMap(model)) { if (ctx.jsonProvider().isMap(model)) {
walkObject(currentPath, model, ctx, predicate, predicateMatches); walkObject(currentPath, model, ctx, predicate, predicateMatches);
} else if (ctx.jsonProvider().isArray(model)) { } else if (ctx.jsonProvider().isArray(model)) {
@ -47,7 +49,7 @@ public class ScanPathToken extends PathToken {
} }
} }
public void walkArray(String currentPath, Object model, EvaluationContextImpl ctx, Predicate predicate, Map<String, Object> predicateMatches) { public static void walkArray(String currentPath, Object model, EvaluationContextImpl ctx, Predicate predicate, Map<String, Object> predicateMatches) {
if (predicate.matches(model)) { if (predicate.matches(model)) {
predicateMatches.put(currentPath, model); predicateMatches.put(currentPath, model);
@ -69,7 +71,7 @@ public class ScanPathToken extends PathToken {
} }
} }
public void walkObject(String currentPath, Object model, EvaluationContextImpl ctx, Predicate predicate, Map<String, Object> predicateMatches) { public static void walkObject(String currentPath, Object model, EvaluationContextImpl ctx, Predicate predicate, Map<String, Object> predicateMatches) {
if (predicate.matches(model)) { if (predicate.matches(model)) {
predicateMatches.put(currentPath, model); predicateMatches.put(currentPath, model);
@ -79,96 +81,124 @@ public class ScanPathToken extends PathToken {
for (String property : properties) { for (String property : properties) {
String evalPath = currentPath + "['" + property + "']"; String evalPath = currentPath + "['" + property + "']";
Object propertyModel = ctx.jsonProvider().getMapValue(model, property); Object propertyModel = ctx.jsonProvider().getMapValue(model, property);
if (propertyModel != JsonProvider.UNDEFINED) {
walk(evalPath, propertyModel, ctx, predicate, predicateMatches); walk(evalPath, propertyModel, ctx, predicate, predicateMatches);
} }
}
} }
private Predicate createScanPredicate(final PathToken target, final EvaluationContextImpl ctx) { private static Predicate createScanPredicate(final PathToken target, final EvaluationContextImpl ctx) {
if (target instanceof PropertyPathToken) { if (target instanceof PropertyPathToken) {
return new Predicate() { return new PropertyPathTokenPredicate(target, ctx);
private PropertyPathToken propertyPathToken = (PropertyPathToken) target; } else if (target instanceof ArrayPathToken) {
return new ArrayPathTokenPredicate(ctx);
} else if (target instanceof WildcardPathToken) {
return new WildcardPathTokenPredicate();
} else if (target instanceof FilterPathToken) {
return new FilterPathTokenPredicate(target, ctx);
} else {
return FALSE_PREDICATE;
}
}
@Override @Override
public Class<?> clazz() { boolean isTokenDefinite() {
return PropertyPathToken.class; return false;
} }
@Override @Override
public boolean matches(Object model) { public String getPathFragment() {
Collection<String> keys = ctx.jsonProvider().getPropertyKeys(model); return "..";
return keys.containsAll(propertyPathToken.getProperties());
} }
};
} else if (target instanceof ArrayPathToken) {
return new Predicate() {
private static interface Predicate {
Class<?> clazz();
boolean matches(Object model);
}
private static final Predicate FALSE_PREDICATE = new Predicate() {
@Override @Override
public Class<?> clazz() { public Class<?> clazz() {
return ArrayPathToken.class; return null;
} }
@Override @Override
public boolean matches(Object model) { public boolean matches(Object model) {
return ctx.jsonProvider().isArray(model); return false;
} }
}; };
} else if (target instanceof WildcardPathToken) {
return new Predicate() { private static final class FilterPathTokenPredicate implements Predicate {
private final EvaluationContextImpl ctx;
private FilterPathToken filterPathToken;
private FilterPathTokenPredicate(PathToken target, EvaluationContextImpl ctx) {
this.ctx = ctx;
filterPathToken = (FilterPathToken) target;
}
@Override @Override
public Class<?> clazz() { public Class<?> clazz() {
return WildcardPathToken.class; return FilterPathToken.class;
} }
@Override @Override
public boolean matches(Object model) { public boolean matches(Object model) {
return true; return filterPathToken.accept(model, ctx.configuration());
}
} }
};
} else if (target instanceof FilterPathToken) {
return new Predicate() {
private FilterPathToken filterPathToken = (FilterPathToken) target;
private static final class WildcardPathTokenPredicate implements Predicate {
@Override @Override
public Class<?> clazz() { public Class<?> clazz() {
return FilterPathToken.class; return WildcardPathToken.class;
} }
@Override @Override
public boolean matches(Object model) { public boolean matches(Object model) {
return filterPathToken.accept(model, ctx.configuration()); return true;
} }
}; }
} else {
return new Predicate() { private static final class ArrayPathTokenPredicate implements Predicate {
private final EvaluationContextImpl ctx;
private ArrayPathTokenPredicate(EvaluationContextImpl ctx) {
this.ctx = ctx;
}
@Override @Override
public Class<?> clazz() { public Class<?> clazz() {
return null; return ArrayPathToken.class;
} }
@Override @Override
public boolean matches(Object model) { public boolean matches(Object model) {
return false; return ctx.jsonProvider().isArray(model);
}
};
} }
} }
private static final class PropertyPathTokenPredicate implements Predicate {
private final EvaluationContextImpl ctx;
private PropertyPathToken propertyPathToken;
@Override private PropertyPathTokenPredicate(PathToken target, EvaluationContextImpl ctx) {
boolean isTokenDefinite() { this.ctx = ctx;
return false; propertyPathToken = (PropertyPathToken) target;
} }
@Override @Override
public String getPathFragment() { public Class<?> clazz() {
return ".."; return PropertyPathToken.class;
} }
private interface Predicate { @Override
Class<?> clazz(); public boolean matches(Object model) {
Collection<String> keys = ctx.jsonProvider().getPropertyKeys(model);
boolean matches(Object model); return keys.containsAll(propertyPathToken.getProperties());
}
} }
} }

16
json-path/src/main/java/com/jayway/jsonpath/internal/spi/json/AbstractJsonProvider.java

@ -50,23 +50,11 @@ public abstract class AbstractJsonProvider implements JsonProvider {
* *
* @param obj a map * @param obj a map
* @param key property key * @param key property key
* @return the map entry * @return the map entry or {@link com.jayway.jsonpath.spi.json.JsonProvider#UNDEFINED} for missing properties
*/ */
public Object getMapValue(Object obj, String key){ public Object getMapValue(Object obj, String key){
return ((Map) obj).get(key);
}
/**
* Extracts a value from an map
*
* @param obj a map
* @param key property key
* @param signalUndefined if true the constant {@link com.jayway.jsonpath.spi.json.JsonProvider#UNDEFINED} is returned for missing properties
* @return the map entry
*/
public Object getMapValue(Object obj, String key, boolean signalUndefined){
Map m = (Map) obj; Map m = (Map) obj;
if(!m.containsKey(key) && signalUndefined){ if(!m.containsKey(key)){
return JsonProvider.UNDEFINED; return JsonProvider.UNDEFINED;
} else { } else {
return m.get(key); return m.get(key);

12
json-path/src/main/java/com/jayway/jsonpath/spi/json/JsonProvider.java

@ -83,20 +83,10 @@ public interface JsonProvider {
* *
* @param obj a map * @param obj a map
* @param key property key * @param key property key
* @return the map entry * @return the map entry or {@link com.jayway.jsonpath.spi.json.JsonProvider#UNDEFINED} for missing properties
*/ */
Object getMapValue(Object obj, String key); Object getMapValue(Object obj, String key);
/**
* Extracts a value from an map
*
* @param obj a map
* @param key property key
* @param signalUndefined if true the constant {@link com.jayway.jsonpath.spi.json.JsonProvider#UNDEFINED} is returned for missing properties
* @return the map entry
*/
Object getMapValue(Object obj, String key, boolean signalUndefined);
/** /**
* Sets a value in an object or array * Sets a value in an object or array
* *

Loading…
Cancel
Save