Browse Source

Code clean up and JacksonProvider improvements.

pull/41/head
Kalle Stenflo 10 years ago
parent
commit
0d8192170a
  1. 58
      json-path-web-test/src/main/java/com/jayway/jsonpath/web/bench/Bench.java
  2. 2
      json-path-web-test/src/main/java/com/jayway/jsonpath/web/resource/IndexResource.java
  3. 10
      json-path/src/main/java/com/jayway/jsonpath/Configuration.java
  4. 11
      json-path/src/main/java/com/jayway/jsonpath/Option.java
  5. 148
      json-path/src/main/java/com/jayway/jsonpath/internal/spi/compiler/ArrayPathToken.java
  6. 10
      json-path/src/main/java/com/jayway/jsonpath/internal/spi/compiler/CompiledPath.java
  7. 16
      json-path/src/main/java/com/jayway/jsonpath/internal/spi/compiler/PathCompiler.java
  8. 56
      json-path/src/main/java/com/jayway/jsonpath/internal/spi/compiler/PathToken.java
  9. 23
      json-path/src/main/java/com/jayway/jsonpath/internal/spi/compiler/PropertyPathToken.java
  10. 3
      json-path/src/main/java/com/jayway/jsonpath/internal/spi/compiler/ScanPathToken.java
  11. 4
      json-path/src/main/java/com/jayway/jsonpath/internal/spi/compiler/WildcardPathToken.java
  12. 21
      json-path/src/main/java/com/jayway/jsonpath/internal/spi/json/JacksonProvider.java
  13. 3
      json-path/src/main/java/com/jayway/jsonpath/spi/compiler/Path.java
  14. 6
      json-path/src/main/java/com/jayway/jsonpath/spi/json/JsonProviderFactory.java
  15. 4
      json-path/src/test/java/com/jayway/jsonpath/Runner.java

58
json-path-web-test/src/main/java/com/jayway/jsonpath/web/bench/Bench.java

@ -21,12 +21,16 @@ public class Bench {
protected final String json; protected final String json;
protected final String path; protected final String path;
private final boolean value; private final boolean optionAsValues;
private final boolean optionAllwaysReturnList;
private final boolean optionMergeMultiProps;
public Bench(String json, String path, boolean value) { public Bench(String json, String path, boolean optionAsValues, boolean optionAllwaysReturnList, boolean optionMergeMultiProps) {
this.json = json; this.json = json;
this.path = path; this.path = path;
this.value = value; this.optionAsValues = optionAsValues;
this.optionAllwaysReturnList = optionAllwaysReturnList;
this.optionMergeMultiProps = optionMergeMultiProps;
} }
public Result runJayway() { public Result runJayway() {
@ -35,33 +39,31 @@ public class Bench {
long time; long time;
Object res = null; Object res = null;
//Configuration configuration = Configuration.defaultConfiguration();
Configuration configuration = Configuration.defaultConfiguration().options(Option.ALWAYS_RETURN_LIST); Configuration configuration = Configuration.defaultConfiguration();
if(!value){ if(optionAllwaysReturnList){
configuration = configuration.options(Option.AS_PATH_LIST); configuration = configuration.addOptions(Option.ALWAYS_RETURN_LIST);
}
if(optionMergeMultiProps){
configuration = configuration.addOptions(Option.MERGE_MULTI_PROPS);
}
if (!optionAsValues) {
configuration = configuration.addOptions(Option.AS_PATH_LIST);
} }
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
try { try {
res = JsonPath.using(configuration).parse(json).read(path); res = JsonPath.using(configuration).parse(json).read(path);
/* } catch (Exception e) {
if(value) {
res = JsonPath.parse(json).read(path);
} else {
res = JsonPath.parse(json).readPathList(path);
}*/
} catch (Exception e){
error = getError(e); error = getError(e);
} finally { } finally {
time = System.currentTimeMillis() - now; time = System.currentTimeMillis() - now;
if(res instanceof String) { if (res instanceof String) {
result = "\"" + res + "\""; result = "\"" + res + "\"";
} else if(res instanceof Number) { } else if (res instanceof Number) {
result = res.toString(); result = res.toString();
} else if(res instanceof Boolean){ } else if (res instanceof Boolean) {
result = res.toString(); result = res.toString();
} else { } else {
result = res != null ? JsonProviderFactory.createProvider().toJson(res) : "null"; result = res != null ? JsonProviderFactory.createProvider().toJson(res) : "null";
@ -78,7 +80,7 @@ public class Bench {
Iterator<Object> query = null; Iterator<Object> query = null;
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
try { try {
if(!value){ if (!optionAsValues) {
throw new UnsupportedOperationException("Not supported!"); throw new UnsupportedOperationException("Not supported!");
} }
io.gatling.jsonpath.JsonPath jsonPath = JsonPath$.MODULE$.compile(path).right().get(); io.gatling.jsonpath.JsonPath jsonPath = JsonPath$.MODULE$.compile(path).right().get();
@ -87,12 +89,12 @@ public class Bench {
Object jsonModel = jsonParser.parse(json); Object jsonModel = jsonParser.parse(json);
query = jsonPath.query(jsonModel); query = jsonPath.query(jsonModel);
} catch (Exception e){ } catch (Exception e) {
error = getError(e); error = getError(e);
} finally { } finally {
time = System.currentTimeMillis() - now; time = System.currentTimeMillis() - now;
if(query != null) { if (query != null) {
List<Object> res = new ArrayList<Object>(); List<Object> res = new ArrayList<Object>();
while (query.hasNext()) { while (query.hasNext()) {
res.add(query.next()); res.add(query.next());
@ -113,27 +115,27 @@ public class Bench {
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
try { try {
if(!value){ if (!optionAsValues) {
throw new UnsupportedOperationException("Not supported!"); throw new UnsupportedOperationException("Not supported!");
} }
com.nebhale.jsonpath.JsonPath compiled = com.nebhale.jsonpath.JsonPath.compile(path); com.nebhale.jsonpath.JsonPath compiled = com.nebhale.jsonpath.JsonPath.compile(path);
res = compiled.read(json, Object.class); res = compiled.read(json, Object.class);
} catch (Exception e){ } catch (Exception e) {
error = getError(e); error = getError(e);
} finally { } finally {
time = System.currentTimeMillis() - now; time = System.currentTimeMillis() - now;
result = res!=null? jacksonProvider.toJson(res):null; result = res != null ? jacksonProvider.toJson(res) : null;
return new Result("nebhale", time, result, error); return new Result("nebhale", time, result, error);
} }
} }
public List<Result> runAll(){ public List<Result> runAll() {
return asList(runJayway(), runBoon(), runNebhale()); return asList(runJayway(), runBoon(), runNebhale());
} }
private String getError(Exception e){ private String getError(Exception e) {
String ex = e.getMessage(); String ex = e.getMessage();
if(ex == null || ex.trim().isEmpty()){ if (ex == null || ex.trim().isEmpty()) {
ex = "Undefined error"; ex = "Undefined error";
} }
return ex; return ex;

2
json-path-web-test/src/main/java/com/jayway/jsonpath/web/resource/IndexResource.java

@ -45,7 +45,7 @@ public class IndexResource {
boolean value = "VALUE".equalsIgnoreCase(type); boolean value = "VALUE".equalsIgnoreCase(type);
return createView(json, path, value, template, new Bench(json, path, value).runAll()); return createView(json, path, value, template, new Bench(json, path, value, true, true).runAll());
} }
private Viewable createView(String json, String path, boolean value, String selectedTemplate, List<Result> results){ private Viewable createView(String json, String path, boolean value, String selectedTemplate, List<Result> results){

10
json-path/src/main/java/com/jayway/jsonpath/Configuration.java

@ -17,12 +17,12 @@ package com.jayway.jsonpath;
import com.jayway.jsonpath.spi.json.JsonProvider; import com.jayway.jsonpath.spi.json.JsonProvider;
import com.jayway.jsonpath.spi.json.JsonProviderFactory; import com.jayway.jsonpath.spi.json.JsonProviderFactory;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.Set; import java.util.Set;
import static com.jayway.jsonpath.internal.Utils.notNull; import static com.jayway.jsonpath.internal.Utils.notNull;
import static java.util.Arrays.asList;
public class Configuration { public class Configuration {
@ -44,6 +44,12 @@ public class Configuration {
return provider; return provider;
} }
public Configuration addOptions(Option... options) {
EnumSet<Option> opts = EnumSet.noneOf(Option.class);
opts.addAll(this.options);
opts.addAll(asList(options));
return Configuration.builder().jsonProvider(provider).options(opts).build();
}
public Configuration options(Option... options) { public Configuration options(Option... options) {
return Configuration.builder().jsonProvider(provider).options(options).build(); return Configuration.builder().jsonProvider(provider).options(options).build();
} }
@ -71,7 +77,7 @@ public class Configuration {
} }
public ConfigurationBuilder options(Option... flags) { public ConfigurationBuilder options(Option... flags) {
this.options.addAll(Arrays.asList(flags)); this.options.addAll(asList(flags));
return this; return this;
} }

11
json-path/src/main/java/com/jayway/jsonpath/Option.java

@ -23,15 +23,18 @@ public enum Option {
/** /**
* Makes this implementation more compliant to the Goessner spec. All results are returned as Lists. * Makes this implementation more compliant to the Goessner spec. All results are returned as Lists.
*
*/ */
ALWAYS_RETURN_LIST, ALWAYS_RETURN_LIST,
/** /**
* returns a list of path strings representing the path of the evaluation hits * Returns a list of path strings representing the path of the evaluation hits
*
*/ */
AS_PATH_LIST AS_PATH_LIST,
/**
* When multiple properties are queried eg @..['foo', 'bar'] these properties are extracted and put in a new Map.
*/
MERGE_MULTI_PROPS
} }

148
json-path/src/main/java/com/jayway/jsonpath/internal/spi/compiler/ArrayPathToken.java

@ -46,75 +46,87 @@ class ArrayPathToken extends PathToken {
} }
try { try {
if (operation == Operation.SINGLE_INDEX) { int idx;
handleArrayIndex(criteria.get(0), currentPath, model, ctx); int input;
} else if (operation == Operation.INDEX_SEQUENCE) { int length;
for (Integer idx : criteria) { int from;
handleArrayIndex(criteria.get(idx), currentPath, model, ctx); int to;
switch (operation){
case SINGLE_INDEX:
handleArrayIndex(criteria.get(0), currentPath, model, ctx);
break;
case INDEX_SEQUENCE:
for (Integer i : criteria) {
handleArrayIndex(criteria.get(i), currentPath, model, ctx);
}
break;
case CONTEXT_SIZE:
length = ctx.jsonProvider().length(model);
idx = length + criteria.get(0);
handleArrayIndex(idx, currentPath, model, ctx);
break;
case SLICE_FROM: //[2:]
input = criteria.get(0);
length = ctx.jsonProvider().length(model);
from = input;
if (from < 0) {
//calculate slice start from array length
from = length + from;
}
from = Math.max(0, from);
logger.debug("Slice from index on array with length: {}. From index: {} to: {}. Input: {}", length, from, length - 1, toString());
if (length == 0 || from >= length) {
return;
}
for (int i = from; i < length; i++) {
handleArrayIndex(i, currentPath, model, ctx);
}
break;
case SLICE_TO : //[:2]
input = criteria.get(0);
length = ctx.jsonProvider().length(model);
to = input;
if (to < 0) {
//calculate slice end from array length
to = length + to;
}
to = Math.min(length, to);
logger.debug("Slice to index on array with length: {}. From index: 0 to: {}. Input: {}", length, to, toString());
if (length == 0) {
return;
}
for (int i = 0; i < to; i++) {
handleArrayIndex(i, currentPath, model, ctx);
}
break;
case SLICE_BETWEEN : //[2:4]
from = criteria.get(0);
to = criteria.get(1);
length = ctx.jsonProvider().length(model);
to = Math.min(length, to);
if (from >= to || length == 0) {
return;
}
logger.debug("Slice between indexes on array with length: {}. From index: {} to: {}. Input: {}", length, from, to, toString());
for (int i = from; i < to; i++) {
handleArrayIndex(i, currentPath, model, ctx);
}
break;
} }
} else if (Operation.CONTEXT_SIZE == operation) {
int length = ctx.jsonProvider().length(model);
int idx = length + criteria.get(0);
handleArrayIndex(idx, currentPath, model, ctx);
}
//[2:]
else if (Operation.SLICE_FROM == operation) {
int input = criteria.get(0);
int length = ctx.jsonProvider().length(model);
int from = input;
if (from < 0) {
//calculate slice start from array length
from = length + from;
}
from = Math.max(0, from);
logger.debug("Slice from index on array with length: {}. From index: {} to: {}. Input: {}", length, from, length - 1, toString());
if (length == 0 || from >= length) {
return;
}
for (int i = from; i < length; i++) {
handleArrayIndex(i, currentPath, model, ctx);
}
}
//[:2]
else if (Operation.SLICE_TO == operation) {
int input = criteria.get(0);
int length = ctx.jsonProvider().length(model);
int to = input;
if (to < 0) {
//calculate slice end from array length
to = length + to;
}
to = Math.min(length, to);
logger.debug("Slice to index on array with length: {}. From index: 0 to: {}. Input: {}", length, to, toString());
if (length == 0) {
return;
}
for (int i = 0; i < to; i++) {
handleArrayIndex(i, currentPath, model, ctx);
}
}
//[2:4]
else if (Operation.SLICE_BETWEEN == operation) {
int from = criteria.get(0);
int to = criteria.get(1);
int length = ctx.jsonProvider().length(model);
to = Math.min(length, to);
if (from >= to || length == 0) {
return;
}
logger.debug("Slice between indexes on array with length: {}. From index: {} to: {}. Input: {}", length, from, to, toString());
for (int i = from; i < to; i++) {
handleArrayIndex(i, currentPath, model, ctx);
}
}
} catch (IndexOutOfBoundsException e) { } catch (IndexOutOfBoundsException e) {
throw new PathNotFoundException("Index out of bounds when evaluating path " + currentPath); throw new PathNotFoundException("Index out of bounds when evaluating path " + currentPath);
} }

10
json-path/src/main/java/com/jayway/jsonpath/internal/spi/compiler/CompiledPath.java

@ -1,7 +1,6 @@
package com.jayway.jsonpath.internal.spi.compiler; package com.jayway.jsonpath.internal.spi.compiler;
import com.jayway.jsonpath.Configuration; import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.internal.JsonFormatter;
import com.jayway.jsonpath.spi.compiler.EvaluationContext; import com.jayway.jsonpath.spi.compiler.EvaluationContext;
import com.jayway.jsonpath.spi.compiler.Path; import com.jayway.jsonpath.spi.compiler.Path;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -27,10 +26,6 @@ class CompiledPath implements Path {
EvaluationContextImpl ctx = new EvaluationContextImpl(this, configuration); EvaluationContextImpl ctx = new EvaluationContextImpl(this, configuration);
root.evaluate("", model, ctx); root.evaluate("", model, ctx);
if(logger.isDebugEnabled()) {
logger.debug("Found:\n{}", JsonFormatter.prettyPrint(ctx.configuration().getProvider().toJson(ctx.getPathList())));
}
return ctx; return ctx;
} }
@ -39,11 +34,6 @@ class CompiledPath implements Path {
return root.isPathDefinite(); return root.isPathDefinite();
} }
@Override
public int tokenCount() {
return root.getTokenCount();
}
@Override @Override
public String toString() { public String toString() {
return root.toString(); return root.toString();

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

@ -45,7 +45,7 @@ public class PathCompiler {
String cacheKey = path + filterList.toString(); String cacheKey = path + filterList.toString();
Path p = cache.get(cacheKey); Path p = cache.get(cacheKey);
if(p != null){ if(p != null){
return p; //return p;
} }
RootPathToken root = null; RootPathToken root = null;
@ -340,37 +340,31 @@ public class PathCompiler {
//"['foo']" //"['foo']"
private PathToken analyzeProperty() { private PathToken analyzeProperty() {
String property = null; List<String> properties = new ArrayList<String>();
StringBuilder buffer = new StringBuilder(); StringBuilder buffer = new StringBuilder();
boolean propertyIsOpen = false; boolean propertyIsOpen = false;
boolean propertyDone = false;
while (current != ']') { while (current != ']') {
switch (current) { switch (current) {
case '\'': case '\'':
if (propertyIsOpen) { if (propertyIsOpen) {
property = buffer.toString(); properties.add(buffer.toString());
buffer = new StringBuilder();
propertyIsOpen = false; propertyIsOpen = false;
propertyDone = true;
} else { } else {
propertyIsOpen = true; propertyIsOpen = true;
} }
break; break;
default: default:
if (propertyIsOpen) { if (propertyIsOpen) {
if(propertyDone){
//Don't understand how to create a "Normalized path expressions" for this type of query
throw new InvalidPathException("Only single properties are supported.");
}
buffer.append(current); buffer.append(current);
} }
break; break;
} }
current = chars[++i]; current = chars[++i];
} }
return new PropertyPathToken(property); return new PropertyPathToken(properties);
} }

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

@ -1,7 +1,11 @@
package com.jayway.jsonpath.internal.spi.compiler; package com.jayway.jsonpath.internal.spi.compiler;
import com.jayway.jsonpath.InvalidPathException;
import com.jayway.jsonpath.Option; import com.jayway.jsonpath.Option;
import com.jayway.jsonpath.PathNotFoundException; import com.jayway.jsonpath.PathNotFoundException;
import com.jayway.jsonpath.internal.Utils;
import java.util.List;
/** /**
* *
@ -16,20 +20,58 @@ abstract class PathToken {
return next; return next;
} }
void handleObjectProperty(String currentPath, Object model, EvaluationContextImpl ctx, String property) { void handleObjectProperty(String currentPath, Object model, EvaluationContextImpl ctx, List<String> properties) {
String evalPath = currentPath + "['" + property + "']";
Object propertyVal = readObjectProperty(property, model, ctx); if(properties.size() == 1) {
if (isLeaf()) { String property = properties.get(0);
ctx.addResult(evalPath, propertyVal); String evalPath = currentPath + "['" + property + "']";
Object propertyVal = readObjectProperty(property, model, ctx);
if (isLeaf()) {
ctx.addResult(evalPath, propertyVal);
} else {
next().evaluate(evalPath, propertyVal, ctx);
}
} else { } else {
next().evaluate(evalPath, propertyVal, ctx); if(ctx.configuration().getOptions().contains(Option.MERGE_MULTI_PROPS)) {
String evalPath = currentPath + "[" + Utils.join(", ", "'", properties) + "]";
if (!isLeaf()) {
throw new InvalidPathException("Multi properties can only be used as path leafs: " + evalPath);
} else {
Object map = ctx.jsonProvider().createMap();
for (String property : properties) {
if(hasProperty(property, model, ctx)) {
Object propertyVal = readObjectProperty(property, model, ctx);
ctx.jsonProvider().setProperty(map, property, propertyVal);
}
}
ctx.addResult(evalPath, map);
}
} else {
if (!isLeaf()) {
String evalPath = currentPath + "[" + Utils.join(", ", "'", properties) + "]";
throw new InvalidPathException("Multi properties can only be used as path leafs: " + evalPath);
} else {
for (String property : properties) {
String evalPath = currentPath + "['" + property + "']";
if(hasProperty(property, model, ctx)) {
Object propertyVal = readObjectProperty(property, model, ctx);
ctx.addResult(evalPath, propertyVal);
}
}
}
}
} }
} }
private boolean hasProperty(String property, Object model, EvaluationContextImpl ctx) {
return ctx.jsonProvider().getPropertyKeys(model).contains(property);
}
private Object readObjectProperty(String property, Object model, EvaluationContextImpl ctx) { private Object readObjectProperty(String property, Object model, EvaluationContextImpl ctx) {
if (ctx.options().contains(Option.THROW_ON_MISSING_PROPERTY) && !ctx.jsonProvider().getPropertyKeys(model).contains(property)) { if (ctx.options().contains(Option.THROW_ON_MISSING_PROPERTY) && !ctx.jsonProvider().getPropertyKeys(model).contains(property)) {
throw new PathNotFoundException("Path [" + property + "] not found in the current context:\n" + ctx.jsonProvider().toJson(model)); throw new PathNotFoundException("Path [" + property + "] not found in the current context" );
} }
return ctx.jsonProvider().getProperty(model, property); return ctx.jsonProvider().getProperty(model, property);
} }

23
json-path/src/main/java/com/jayway/jsonpath/internal/spi/compiler/PropertyPathToken.java

@ -1,29 +1,32 @@
package com.jayway.jsonpath.internal.spi.compiler; package com.jayway.jsonpath.internal.spi.compiler;
import com.jayway.jsonpath.PathNotFoundException; import com.jayway.jsonpath.PathNotFoundException;
import com.jayway.jsonpath.internal.Utils;
import java.util.List;
/** /**
* *
*/ */
class PropertyPathToken extends PathToken { class PropertyPathToken extends PathToken {
private final String property; private final List<String> properties;
public PropertyPathToken(String property) { public PropertyPathToken(List<String> properties) {
this.property = property; this.properties = properties;
} }
public String getProperty() { public List<String> getProperties() {
return property; return properties;
} }
@Override @Override
void evaluate(String currentPath, Object model, EvaluationContextImpl ctx) { void evaluate(String currentPath, Object model, EvaluationContextImpl ctx) {
if (!ctx.jsonProvider().isMap(model)) { if (!ctx.jsonProvider().isMap(model)) {
throw new PathNotFoundException("Property ['" + property + "'] not found in path " + currentPath); throw new PathNotFoundException("Property " + getPathFragment() + " not found in path " + currentPath);
} }
handleObjectProperty(currentPath, model, ctx, property); handleObjectProperty(currentPath, model, ctx, properties);
} }
@Override @Override
@ -34,8 +37,8 @@ class PropertyPathToken extends PathToken {
@Override @Override
public String getPathFragment() { public String getPathFragment() {
return new StringBuilder() return new StringBuilder()
.append("['") .append("[")
.append(property) .append(Utils.join(", ", "'", properties))
.append("']").toString(); .append("]").toString();
} }
} }

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

@ -86,7 +86,6 @@ class ScanPathToken extends PathToken {
private Predicate createScanPredicate(final PathToken target, final EvaluationContextImpl ctx) { private Predicate createScanPredicate(final PathToken target, final EvaluationContextImpl ctx) {
if (target instanceof PropertyPathToken) { if (target instanceof PropertyPathToken) {
return new Predicate() { return new Predicate() {
private PropertyPathToken propertyPathToken = (PropertyPathToken) target; private PropertyPathToken propertyPathToken = (PropertyPathToken) target;
@ -98,7 +97,7 @@ class ScanPathToken extends PathToken {
@Override @Override
public boolean matches(Object model) { public boolean matches(Object model) {
Collection<String> keys = ctx.jsonProvider().getPropertyKeys(model); Collection<String> keys = ctx.jsonProvider().getPropertyKeys(model);
return keys.contains(propertyPathToken.getProperty()); return keys.containsAll(propertyPathToken.getProperties());
} }
}; };
} else if (target instanceof ArrayPathToken) { } else if (target instanceof ArrayPathToken) {

4
json-path/src/main/java/com/jayway/jsonpath/internal/spi/compiler/WildcardPathToken.java

@ -1,5 +1,7 @@
package com.jayway.jsonpath.internal.spi.compiler; package com.jayway.jsonpath.internal.spi.compiler;
import static java.util.Arrays.asList;
/** /**
* *
*/ */
@ -9,7 +11,7 @@ class WildcardPathToken extends PathToken {
void evaluate(String currentPath, Object model, EvaluationContextImpl ctx) { void evaluate(String currentPath, Object model, EvaluationContextImpl ctx) {
if (ctx.jsonProvider().isMap(model)) { if (ctx.jsonProvider().isMap(model)) {
for (String property : ctx.jsonProvider().getPropertyKeys(model)) { for (String property : ctx.jsonProvider().getPropertyKeys(model)) {
handleObjectProperty(currentPath, model, ctx, property); handleObjectProperty(currentPath, model, ctx, asList(property));
} }
} else if (ctx.jsonProvider().isArray(model)) { } else if (ctx.jsonProvider().isArray(model)) {
for (int idx = 0; idx < ctx.jsonProvider().length(model); idx++) { for (int idx = 0; idx < ctx.jsonProvider().length(model); idx++) {

21
json-path/src/main/java/com/jayway/jsonpath/internal/spi/json/JacksonProvider.java

@ -16,6 +16,7 @@ package com.jayway.jsonpath.internal.spi.json;
import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
import com.jayway.jsonpath.InvalidJsonException; import com.jayway.jsonpath.InvalidJsonException;
import com.jayway.jsonpath.spi.json.Mode; import com.jayway.jsonpath.spi.json.Mode;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -25,7 +26,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.Reader; import java.io.Reader;
import java.io.StringWriter; import java.io.StringWriter;
import java.util.HashMap; import java.util.LinkedHashMap;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -34,9 +35,9 @@ public class JacksonProvider extends AbstractJsonProvider {
private static final Logger logger = LoggerFactory.getLogger(JacksonProvider.class); private static final Logger logger = LoggerFactory.getLogger(JacksonProvider.class);
private ObjectMapper objectMapper = new ObjectMapper(); private static final ObjectMapper objectMapper = new ObjectMapper();
private static final ObjectReader objectReader = objectMapper.reader().withType(Object.class);
@Override
public Mode getMode() { public Mode getMode() {
return Mode.STRICT; return Mode.STRICT;
} }
@ -44,7 +45,7 @@ public class JacksonProvider extends AbstractJsonProvider {
@Override @Override
public Object parse(String json) throws InvalidJsonException { public Object parse(String json) throws InvalidJsonException {
try { try {
return objectMapper.readValue(json, Object.class); return objectReader.readValue(json);
} catch (IOException e) { } catch (IOException e) {
logger.debug("Invalid JSON: \n" + json); logger.debug("Invalid JSON: \n" + json);
throw new InvalidJsonException(e); throw new InvalidJsonException(e);
@ -54,7 +55,7 @@ public class JacksonProvider extends AbstractJsonProvider {
@Override @Override
public Object parse(Reader jsonReader) throws InvalidJsonException { public Object parse(Reader jsonReader) throws InvalidJsonException {
try { try {
return objectMapper.readValue(jsonReader, Object.class); return objectReader.readValue(jsonReader);
} catch (IOException e) { } catch (IOException e) {
throw new InvalidJsonException(e); throw new InvalidJsonException(e);
} }
@ -63,7 +64,7 @@ public class JacksonProvider extends AbstractJsonProvider {
@Override @Override
public Object parse(InputStream jsonStream) throws InvalidJsonException { public Object parse(InputStream jsonStream) throws InvalidJsonException {
try { try {
return objectMapper.readValue(jsonStream, Object.class); return objectReader.readValue(jsonStream);
} catch (IOException e) { } catch (IOException e) {
throw new InvalidJsonException(e); throw new InvalidJsonException(e);
} }
@ -73,9 +74,11 @@ public class JacksonProvider extends AbstractJsonProvider {
public String toJson(Object obj) { public String toJson(Object obj) {
StringWriter writer = new StringWriter(); StringWriter writer = new StringWriter();
try { try {
JsonGenerator jsonGenerator = objectMapper.getJsonFactory().createJsonGenerator(writer); JsonGenerator generator = objectMapper.getFactory().createGenerator(writer);
objectMapper.writeValue(jsonGenerator, obj); objectMapper.writeValue(generator, obj);
writer.flush();
writer.close(); writer.close();
generator.close();
return writer.getBuffer().toString(); return writer.getBuffer().toString();
} catch (IOException e) { } catch (IOException e) {
throw new InvalidJsonException(); throw new InvalidJsonException();
@ -84,7 +87,7 @@ public class JacksonProvider extends AbstractJsonProvider {
@Override @Override
public Map<String, Object> createMap() { public Map<String, Object> createMap() {
return new HashMap<String, Object>(); return new LinkedHashMap<String, Object>();
} }
@Override @Override

3
json-path/src/main/java/com/jayway/jsonpath/spi/compiler/Path.java

@ -6,10 +6,9 @@ import com.jayway.jsonpath.Configuration;
* *
*/ */
public interface Path { public interface Path {
EvaluationContext evaluate(Object model, Configuration configuration); EvaluationContext evaluate(Object model, Configuration configuration);
boolean isDefinite(); boolean isDefinite();
int tokenCount();
} }

6
json-path/src/main/java/com/jayway/jsonpath/spi/json/JsonProviderFactory.java

@ -14,12 +14,12 @@
*/ */
package com.jayway.jsonpath.spi.json; package com.jayway.jsonpath.spi.json;
import com.jayway.jsonpath.internal.spi.json.JsonSmartJsonProvider; import com.jayway.jsonpath.internal.spi.json.JacksonProvider;
public abstract class JsonProviderFactory { public abstract class JsonProviderFactory {
private static JsonProvider provider = new JsonSmartJsonProvider(); //private static JsonProvider provider = new JsonSmartJsonProvider();
//private static JsonProvider provider = new JacksonProvider(); private static JsonProvider provider = new JacksonProvider();
public static JsonProvider createProvider() { public static JsonProvider createProvider() {
return provider; return provider;

4
json-path/src/test/java/com/jayway/jsonpath/Runner.java

@ -42,10 +42,10 @@ public class Runner {
public static void main(String[] args) { public static void main(String[] args) {
JsonPath jp = JsonPath.compile("$.store.book[3]"); JsonPath jp = JsonPath.compile("$.store.book[*].category");
ReadContext readContext = JsonPath.parse(DOCUMENT); ReadContext readContext = JsonPath.parse(DOCUMENT);
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
for (long i = 0; i < 100000; i++) { for (long i = 0; i < 50000000; i++) {
readContext.read(jp); readContext.read(jp);
} }

Loading…
Cancel
Save