Browse Source

API clean up. Reduce static method overloading by fluent API.

pull/10/merge
Kalle Stenflo 11 years ago
parent
commit
b15cb3ac8f
  1. 82
      json-path/src/main/java/com/jayway/jsonpath/Configuration.java
  2. 173
      json-path/src/main/java/com/jayway/jsonpath/Criteria.java
  3. 37
      json-path/src/main/java/com/jayway/jsonpath/Filter.java
  4. 14
      json-path/src/main/java/com/jayway/jsonpath/InvalidConversionException.java
  5. 102
      json-path/src/main/java/com/jayway/jsonpath/JsonModel.java
  6. 222
      json-path/src/main/java/com/jayway/jsonpath/JsonPath.java
  7. 13
      json-path/src/main/java/com/jayway/jsonpath/Option.java
  8. 20
      json-path/src/main/java/com/jayway/jsonpath/ParseContext.java
  9. 14
      json-path/src/main/java/com/jayway/jsonpath/PathNotFoundException.java
  10. 15
      json-path/src/main/java/com/jayway/jsonpath/ReadContext.java
  11. 107
      json-path/src/main/java/com/jayway/jsonpath/internal/JsonReader.java
  12. 10
      json-path/src/main/java/com/jayway/jsonpath/internal/PathToken.java
  13. 1
      json-path/src/main/java/com/jayway/jsonpath/internal/PathTokenizer.java
  14. 15
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/ArrayEvalFilter.java
  15. 15
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/ArrayIndexFilter.java
  16. 10
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/ArrayQueryFilter.java
  17. 20
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/FieldFilter.java
  18. 6
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/HasFieldFilter.java
  19. 7
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/PassthroughFilter.java
  20. 10
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/PathTokenFilter.java
  21. 6
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/ScanFilter.java
  22. 6
      json-path/src/main/java/com/jayway/jsonpath/internal/filter/WildcardFilter.java
  23. 1
      json-path/src/main/java/com/jayway/jsonpath/spi/impl/AbstractJsonProvider.java
  24. 5
      json-path/src/test/java/com/jayway/jsonpath/ArraySlicingTest.java
  25. 12
      json-path/src/test/java/com/jayway/jsonpath/ExpressionEvalTest.java
  26. 9
      json-path/src/test/java/com/jayway/jsonpath/FilterTest.java
  27. 17
      json-path/src/test/java/com/jayway/jsonpath/IssuesTest.java
  28. 1
      json-path/src/test/java/com/jayway/jsonpath/JsonModelTest.java
  29. 5
      json-path/src/test/java/com/jayway/jsonpath/PathTest.java
  30. 43
      json-path/src/test/java/com/jayway/jsonpath/reader/ReadConfigurationTest.java

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

@ -0,0 +1,82 @@
package com.jayway.jsonpath;
import com.jayway.jsonpath.spi.JsonProvider;
import com.jayway.jsonpath.spi.JsonProviderFactory;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Set;
import static org.apache.commons.lang3.Validate.notNull;
/**
* User: kalle
* Date: 8/30/13
* Time: 12:05 PM
*/
public class Configuration {
private final JsonProvider provider;
private final EnumSet<Option> options;
private Configuration(JsonProvider provider, EnumSet<Option> options) {
notNull(provider, "provider can not be null");
notNull(options, "options can not be null");
this.provider = provider;
this.options = options;
}
public Configuration provider(JsonProvider provider){
return Configuration.builder().jsonProvider(provider).options(options).build();
}
public JsonProvider getProvider() {
return provider;
}
public Configuration options(Option... options){
return Configuration.builder().jsonProvider(provider).options(options).build();
}
public Set<Option> getOptions() {
return Collections.unmodifiableSet(options);
}
public static Configuration defaultConfiguration(){
return new Configuration(JsonProviderFactory.createProvider(), EnumSet.noneOf(Option.class));
}
public static ConfigurationBuilder builder(){
return new ConfigurationBuilder();
}
public static class ConfigurationBuilder {
private JsonProvider provider;
private EnumSet<Option> options = EnumSet.noneOf(Option.class);
public ConfigurationBuilder jsonProvider(JsonProvider provider) {
this.provider = provider;
return this;
}
public ConfigurationBuilder options(Option... flags) {
this.options.addAll(Arrays.asList(flags));
return this;
}
public ConfigurationBuilder options(Set<Option> options) {
this.options.addAll(options);
return this;
}
public Configuration build(){
if(provider == null){
provider = JsonProviderFactory.createProvider();
}
return new Configuration(provider, options);
}
}
}

173
json-path/src/main/java/com/jayway/jsonpath/Criteria.java

@ -14,7 +14,6 @@
*/
package com.jayway.jsonpath;
import com.jayway.jsonpath.spi.JsonProvider;
import org.apache.commons.lang3.Validate;
import java.util.*;
@ -74,7 +73,7 @@ public class Criteria {
this.key = JsonPath.compile(key);
}
public JsonPath getKey() {
JsonPath getKey() {
return this.key;
}
@ -84,13 +83,13 @@ public class Criteria {
* @param map map to check
* @return true if criteria is a match
*/
public boolean matches(Map<String, Object> map) {
boolean matches(Map<String, Object> map, Configuration configuration) {
if (this.criteriaChain.size() == 1) {
return criteriaChain.get(0).singleObjectApply(map);
return criteriaChain.get(0).singleObjectApply(map, configuration);
} else {
for (Criteria c : this.criteriaChain) {
if (!c.singleObjectApply(map)) {
if (!c.singleObjectApply(map, configuration)) {
return false;
}
}
@ -98,21 +97,21 @@ public class Criteria {
}
}
private static Object readSafely(JsonPath path, Map<String, Object> map){
try{
return path.read(map);
} catch (InvalidPathException e){
return null;
}
private static Object readSafely(JsonPath path, Map<String, Object> map) {
try {
return path.read(map);
} catch (InvalidPathException e) {
return null;
}
}
private static <T> boolean objectOrAnyCollectionItemMatches(final Object singleObjectOrCollection,
final Predicate<T> predicate){
if (singleObjectOrCollection instanceof Collection) {
Iterator it = ((Collection) singleObjectOrCollection).iterator();
while (it.hasNext()) {
if (predicate.accept((T) it.next())) {
return true;
final Predicate<T> predicate) {
if (singleObjectOrCollection instanceof Collection) {
Iterator it = ((Collection) singleObjectOrCollection).iterator();
while (it.hasNext()) {
if (predicate.accept((T) it.next())) {
return true;
}
}
return false;
@ -120,11 +119,11 @@ public class Criteria {
return predicate.accept((T) singleObjectOrCollection);
}
boolean singleObjectApply(Map<String, Object> map) {
boolean singleObjectApply(Map<String, Object> map, final Configuration configuration) {
for (CriteriaType key : this.criteria.keySet()) {
Object actualVal = readSafely(this.key, map);
final Object actualVal = readSafely(this.key, map);
final Object expectedVal = this.criteria.get(key);
if (CriteriaType.GT.equals(key)) {
@ -136,10 +135,10 @@ public class Criteria {
final Number expectedNumber = (Number) expectedVal;
return objectOrAnyCollectionItemMatches(actualVal, new Predicate<Number>() {
@Override
public boolean accept(Number value) {
return (value.doubleValue() > expectedNumber.doubleValue());
}
@Override
public boolean accept(Number value) {
return (value.doubleValue() > expectedNumber.doubleValue());
}
});
} else if (CriteriaType.GTE.equals(key)) {
@ -151,10 +150,10 @@ public class Criteria {
final Number expectedNumber = (Number) expectedVal;
return objectOrAnyCollectionItemMatches(actualVal, new Predicate<Number>() {
@Override
public boolean accept(Number value) {
return (value.doubleValue() >= expectedNumber.doubleValue());
}
@Override
public boolean accept(Number value) {
return (value.doubleValue() >= expectedNumber.doubleValue());
}
});
} else if (CriteriaType.LT.equals(key)) {
@ -166,10 +165,10 @@ public class Criteria {
final Number expectedNumber = (Number) expectedVal;
return objectOrAnyCollectionItemMatches(actualVal, new Predicate<Number>() {
@Override
public boolean accept(Number value) {
return (value.doubleValue() < expectedNumber.doubleValue());
}
@Override
public boolean accept(Number value) {
return (value.doubleValue() < expectedNumber.doubleValue());
}
});
} else if (CriteriaType.LTE.equals(key)) {
@ -181,14 +180,14 @@ public class Criteria {
final Number expectedNumber = (Number) expectedVal;
return objectOrAnyCollectionItemMatches(actualVal, new Predicate<Number>() {
@Override
public boolean accept(Number value) {
return (value.doubleValue() <= expectedNumber.doubleValue());
}
@Override
public boolean accept(Number value) {
return (value.doubleValue() <= expectedNumber.doubleValue());
}
});
} else if (CriteriaType.NE.equals(key)) {
return objectOrAnyCollectionItemMatches(actualVal, new Predicate<Object>() {
@Override
@ -231,13 +230,13 @@ public class Criteria {
} else if (CriteriaType.NOT_EMPTY.equals(key)) {
if(actualVal == null){
if (actualVal == null) {
return false;
}
boolean empty = false;
if (actualVal instanceof Collection) {
empty = ((List) actualVal).isEmpty();
} else if(actualVal instanceof String){
} else if (actualVal instanceof String) {
empty = ((String) actualVal).isEmpty();
}
@ -245,53 +244,56 @@ public class Criteria {
} else if (CriteriaType.EXISTS.equals(key)) {
final boolean exp = (Boolean) expectedVal;
return objectOrAnyCollectionItemMatches(map, new Predicate<Object>() {
@Override
public boolean accept(final Object value) {
boolean act = true;
try {
Object val = getKey().read(value);
if(val instanceof Collection){
act = !((Collection) val).isEmpty();
final boolean exp = (Boolean) expectedVal;
return objectOrAnyCollectionItemMatches(map, new Predicate<Object>() {
@Override
public boolean accept(final Object value) {
boolean act = true;
Object res;
try {
res = getKey().read(value, configuration.options(Option.THROW_ON_MISSING_PROPERTY));
if(configuration.getProvider().isArray(res)){
if(getKey().isPathDefinite()){
act = true;
} else {
act = (configuration.getProvider().length(res) > 0);
}
}
} catch (InvalidPathException e) {
act = false;
}
return act == exp;
}
} catch (InvalidPathException e) {
act = false;
}
return act == exp;
}
});
});
} else if (CriteriaType.TYPE.equals(key)) {
final Class<?> exp = (Class<?>) expectedVal;
return objectOrAnyCollectionItemMatches(actualVal, new Predicate<Object>() {
@Override
public boolean accept(Object value) {
Class<?> act = value == null ? null : value.getClass();
if (act == null) {
return false;
} else {
return act.equals(exp);
@Override
public boolean accept(Object value) {
Class<?> act = value == null ? null : value.getClass();
if (act == null) {
return false;
} else {
return act.equals(exp);
}
}
}
});
} else if (CriteriaType.REGEX.equals(key)) {
final Pattern exp = (Pattern) expectedVal;
return objectOrAnyCollectionItemMatches(actualVal, new Predicate<String>() {
@Override
public boolean accept(String value) {
return value != null && exp.matcher(value).matches();
}
@Override
public boolean accept(String value) {
return value != null && exp.matcher(value).matches();
}
});
} else {
throw new UnsupportedOperationException("Criteria type not supported: " + key.name());
@ -303,7 +305,7 @@ public class Criteria {
Collection<Criteria> cs = (Collection<Criteria>) isValue;
for (Criteria crit : cs) {
for (Criteria c : crit.criteriaChain) {
if (!c.singleObjectApply(map)) {
if (!c.singleObjectApply(map, configuration)) {
return false;
}
}
@ -314,13 +316,13 @@ public class Criteria {
return objectOrAnyCollectionItemMatches(actualVal, new Predicate<Object>() {
@Override
public boolean accept(Object value) {
if (isValue == null) {
if (isValue == null) {
return value == null;
} else {
return isValue.equals(value);
}
}
});
}
} else {
@ -450,12 +452,12 @@ public class Criteria {
}
/**
* The <code>in</code> operator is analogous to the SQL IN modifier, allowing you
* to specify an array of possible matches.
*
* @param c the collection containing the values to match against
* @return
*/
* The <code>in</code> operator is analogous to the SQL IN modifier, allowing you
* to specify an array of possible matches.
*
* @param c the collection containing the values to match against
* @return
*/
public Criteria in(Collection<?> c) {
notNull(c, "collection can not be null");
checkFilterCanBeApplied(CriteriaType.IN);
@ -498,6 +500,7 @@ public class Criteria {
public Criteria all(Object... o) {
return all(Arrays.asList(o));
}
/**
* The <code>all</code> operator is similar to $in, but instead of matching any value in the specified array all values in the array must be matched.
*
@ -603,14 +606,14 @@ public class Criteria {
criteriaChain.add(new Criteria("$and").is(asList(criteria)));
return this;
}
private void checkFilterCanBeApplied(CriteriaType type){
if (getKey().getTokenizer().size() > 2){
throw new IllegalArgumentException("Cannot use "+type+" filter on a multi-level path expression");
}
private void checkFilterCanBeApplied(CriteriaType type) {
if (getKey().getTokenizer().size() > 2) {
throw new IllegalArgumentException("Cannot use " + type + " filter on a multi-level path expression");
}
}
private interface Predicate<T> {
boolean accept(T value);
}

37
json-path/src/main/java/com/jayway/jsonpath/Filter.java

@ -14,10 +14,12 @@
*/
package com.jayway.jsonpath;
import java.util.*;
import com.jayway.jsonpath.spi.JsonProvider;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* A filter is used to filter the content of a JSON array in a JSONPath.
*
@ -47,14 +49,15 @@ public abstract class Filter<T> {
/**
* Filters the provided list based on this filter configuration
* @param filterItems items to filter
* @param jsonProvider the json provider that is used to create the result list
* @param configuration the json provider configuration that is used to create the result list
* @return the filtered list
*/
public Object doFilter(Iterable<T> filterItems, JsonProvider jsonProvider) {
Object result = jsonProvider.createArray();
public Object doFilter(Iterable<T> filterItems, Configuration configuration) {
JsonProvider provider = configuration.getProvider();
Object result = provider.createArray();
for (T filterItem : filterItems) {
if (accept(filterItem)) {
jsonProvider.setProperty(result, jsonProvider.length(result), filterItem);
if (accept(filterItem, configuration)) {
provider.setProperty(result, provider.length(result), filterItem);
}
}
return result;
@ -67,6 +70,14 @@ public abstract class Filter<T> {
*/
public abstract boolean accept(T obj);
/**
* Check if this filter will accept or reject the given object
* @param obj item to check
* @param configuration
* @return true if filter matches
*/
public abstract boolean accept(T obj, Configuration configuration);
/**
* Adds a new criteria to this filter
*
@ -88,6 +99,11 @@ public abstract class Filter<T> {
return false;
}
@Override
public boolean accept(T obj, Configuration configuration){
return accept(obj);
}
@Override
public Filter addCriteria(Criteria criteria) {
throw new UnsupportedOperationException("can not add criteria to a FilterAdapter.");
@ -116,8 +132,13 @@ public abstract class Filter<T> {
@Override
public boolean accept(Map<String, Object> map) {
return accept(map, Configuration.defaultConfiguration());
}
@Override
public boolean accept(Map<String, Object> map, Configuration configuration) {
for (Criteria criterion : this.criteria.values()) {
if (!criterion.matches(map)) {
if (!criterion.matches(map, configuration)) {
return false;
}
}

14
json-path/src/main/java/com/jayway/jsonpath/InvalidConversionException.java

@ -1,3 +1,17 @@
/*
* Copyright 2011 the original author or authors.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jayway.jsonpath;
/**

102
json-path/src/main/java/com/jayway/jsonpath/JsonModel.java

@ -16,8 +16,8 @@ package com.jayway.jsonpath;
import com.jayway.jsonpath.internal.ConvertUtils;
import com.jayway.jsonpath.internal.JsonFormatter;
import com.jayway.jsonpath.internal.JsonReader;
import com.jayway.jsonpath.internal.PathToken;
import com.jayway.jsonpath.internal.IOUtils;
import com.jayway.jsonpath.spi.JsonProvider;
import com.jayway.jsonpath.spi.JsonProviderFactory;
import com.jayway.jsonpath.spi.MappingProviderFactory;
@ -28,7 +28,8 @@ import java.net.URL;
import java.util.*;
import static java.util.Arrays.asList;
import static org.apache.commons.lang3.Validate.*;
import static org.apache.commons.lang3.Validate.isTrue;
import static org.apache.commons.lang3.Validate.notNull;
/**
* A JsonModel holds a parsed JSON document and provides easy read and write operations. In contrast to the
@ -41,69 +42,27 @@ public class JsonModel {
private static final JsonPath JSON_PATH_ROOT = JsonPath.compile("$");
private Object jsonObject;
private JsonProvider jsonProvider;
private Configuration configuration;
// --------------------------------------------------------
//
// Constructors
//
// --------------------------------------------------------
private JsonModel(String jsonObject, JsonProvider jsonProvider) {
private JsonModel(Object jsonObject, Configuration configuration) {
notNull(jsonObject, "json can not be null");
notNull(configuration, "configuration can not be null");
this.jsonProvider = jsonProvider;
this.jsonObject = jsonProvider.parse(jsonObject);
}
/**
* Creates a new JsonModel based on a json document.
* Note that the jsonObject must either a {@link List} or a {@link Map}
*
* @param jsonObject the json object
* @param jsonProvider
*/
private JsonModel(Object jsonObject, JsonProvider jsonProvider) {
notNull(jsonObject, "json can not be null");
if (!jsonProvider.isContainer(jsonObject)) {
if (!configuration.getProvider().isContainer(jsonObject)) {
throw new IllegalArgumentException("Invalid container object");
}
this.jsonProvider = jsonProvider;
this.configuration = configuration;
this.jsonObject = jsonObject;
}
/**
* Creates a new JsonModel based on an {@link InputStream}
*
* @param jsonInputStream the input stream
* @param jsonProvider
*/
private JsonModel(InputStream jsonInputStream, JsonProvider jsonProvider) {
notNull(jsonInputStream, "jsonInputStream can not be null");
this.jsonProvider = jsonProvider;
this.jsonObject = jsonProvider.parse(jsonInputStream);
}
/**
* Creates a new JsonModel by fetching the content from the provided URL
*
* @param jsonURL the URL to read
* @param jsonProvider
* @throws IOException failed to load URL
*/
private JsonModel(URL jsonURL, JsonProvider jsonProvider) throws IOException {
notNull(jsonURL, "jsonURL can not be null");
InputStream jsonInputStream = null;
try {
jsonInputStream = jsonURL.openStream();
this.jsonObject = jsonProvider.parse(jsonInputStream);
this.jsonProvider = jsonProvider;
} finally {
IOUtils.closeQuietly(jsonInputStream);
}
}
/**
* Check if this JsonModel is holding a JSON array as to object
@ -111,7 +70,7 @@ public class JsonModel {
* @return true if root is an array
*/
public boolean isList() {
return jsonProvider.isArray(jsonObject);
return configuration.getProvider().isArray(jsonObject);
}
/**
@ -120,7 +79,7 @@ public class JsonModel {
* @return true if root is an object
*/
public boolean isMap() {
return jsonProvider.isMap(jsonObject);
return configuration.getProvider().isMap(jsonObject);
}
/**
@ -154,7 +113,7 @@ public class JsonModel {
isTrue(jsonPath.isPathDefinite(), "hasPath can only be used for definite paths");
try {
get(jsonPath);
jsonPath.read(jsonObject, configuration.options(Option.THROW_ON_MISSING_PROPERTY));
} catch (PathNotFoundException e) {
return false;
}
@ -231,7 +190,7 @@ public class JsonModel {
public <T> T get(JsonPath jsonPath) {
notNull(jsonPath, "jsonPath can not be null");
return jsonPath.read(jsonProvider, jsonObject);
return jsonPath.read(jsonObject, configuration);
}
// --------------------------------------------------------
@ -247,7 +206,7 @@ public class JsonModel {
* @return array operations for this JsonModel
*/
public ArrayOps opsForArray() {
isTrue(jsonProvider.isArray(jsonObject), "This JsonModel is not a JSON array");
isTrue(configuration.getProvider().isArray(jsonObject), "This JsonModel is not a JSON array");
return opsForArray(JSON_PATH_ROOT);
}
@ -338,7 +297,7 @@ public class JsonModel {
* @return
*/
public String toJson(boolean prettyPrint) {
String json = jsonProvider.toJson(jsonObject);
String json = configuration.getProvider().toJson(jsonObject);
if (prettyPrint)
return JsonFormatter.prettyPrint(json);
else
@ -362,7 +321,7 @@ public class JsonModel {
public String toJson(JsonPath jsonPath) {
notNull(jsonPath, "jsonPath can not be null");
return jsonProvider.toJson(get(jsonPath));
return configuration.getProvider().toJson(get(jsonPath));
}
// --------------------------------------------------------
@ -400,11 +359,11 @@ public class JsonModel {
Object subModel = jsonPath.read(jsonObject);
if (!jsonProvider.isContainer(subModel)) {
if (!configuration.getProvider().isContainer(subModel)) {
throw new InvalidModelException("The path " + jsonPath.getPath() + " returned an invalid model " + (subModel != null ? subModel.getClass() : "null"));
}
return new JsonSubModel(subModel, this.jsonProvider, this, jsonPath);
return new JsonSubModel(subModel, this.configuration, this, jsonPath);
}
// --------------------------------------------------------
//
@ -436,15 +395,15 @@ public class JsonModel {
public JsonModel getSubModelDetached(JsonPath jsonPath) {
notNull(jsonPath, "jsonPath can not be null");
Object subModel = jsonPath.read(jsonProvider, jsonObject);
Object subModel = jsonPath.read(jsonObject, configuration);
if (!jsonProvider.isContainer(subModel)) {
if (!configuration.getProvider().isContainer(subModel)) {
throw new InvalidModelException("The path " + jsonPath.getPath() + " returned an invalid model " + (subModel != null ? subModel.getClass() : "null"));
}
subModel = jsonProvider.clone(subModel);
subModel = configuration.getProvider().clone(subModel);
return new JsonModel(subModel, this.jsonProvider);
return new JsonModel(subModel, configuration);
}
// --------------------------------------------------------
@ -500,9 +459,8 @@ public class JsonModel {
*/
public static JsonModel model(JsonProvider jsonProvider, String json) {
notNull(jsonProvider, "jsonProvider can not be null");
notEmpty(json, "json can not be null or empty");
return new JsonModel(json, jsonProvider);
notNull(json, "jsonObject can not be null");
return new JsonModel(new JsonReader(jsonProvider).parse(json).json(), Configuration.builder().jsonProvider(jsonProvider).build());
}
/**
@ -529,7 +487,7 @@ public class JsonModel {
public static JsonModel model(JsonProvider jsonProvider, Object jsonObject) {
notNull(jsonProvider, "jsonProvider can not be null");
notNull(jsonObject, "jsonObject can not be null");
return new JsonModel(jsonObject, jsonProvider);
return new JsonModel(jsonObject, Configuration.builder().jsonProvider(jsonProvider).build());
}
@ -558,7 +516,7 @@ public class JsonModel {
notNull(jsonProvider, "jsonProvider can not be null");
notNull(url, "url can not be null");
return new JsonModel(url, jsonProvider);
return new JsonModel(new JsonReader(jsonProvider).parse(url).json(), Configuration.builder().jsonProvider(jsonProvider).build());
}
/**
@ -586,7 +544,7 @@ public class JsonModel {
notNull(jsonProvider, "jsonProvider can not be null");
notNull(jsonInputStream, "jsonInputStream can not be null");
return new JsonModel(jsonInputStream, jsonProvider);
return new JsonModel(new JsonReader(jsonProvider).parse(jsonInputStream).json(), Configuration.builder().jsonProvider(jsonProvider).build());
}
/**
@ -630,7 +588,7 @@ public class JsonModel {
PathToken currentToken;
do {
currentToken = tokens.poll();
modelRef = currentToken.apply(modelRef, jsonProvider);
modelRef = currentToken.apply(modelRef, this.configuration);
} while (!tokens.isEmpty());
if (modelRef.getClass().isAssignableFrom(clazz)) {
@ -1100,8 +1058,8 @@ public class JsonModel {
private final JsonModel parent;
private final JsonPath subModelPath;
private JsonSubModel(Object jsonObject, JsonProvider jsonProvider, JsonModel parent, JsonPath subModelPath) {
super(jsonObject, jsonProvider);
private JsonSubModel(Object jsonObject, Configuration configuration, JsonModel parent, JsonPath subModelPath) {
super(jsonObject, configuration);
this.parent = parent;
this.subModelPath = subModelPath;
}

222
json-path/src/main/java/com/jayway/jsonpath/JsonPath.java

@ -16,13 +16,13 @@ package com.jayway.jsonpath;
import com.jayway.jsonpath.internal.IOUtils;
import com.jayway.jsonpath.internal.JsonReader;
import com.jayway.jsonpath.internal.PathToken;
import com.jayway.jsonpath.internal.PathTokenizer;
import com.jayway.jsonpath.internal.filter.PathTokenFilter;
import com.jayway.jsonpath.spi.HttpProviderFactory;
import com.jayway.jsonpath.spi.JsonProvider;
import com.jayway.jsonpath.spi.JsonProviderFactory;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -137,7 +137,8 @@ public class JsonPath {
public JsonPath copy() {
return new JsonPath(tokenizer.getPath(), filters.toArray(new Filter[0]));
Filter[] filterCopy = filters.isEmpty()?new Filter[0]:new Filter[filters.size()];
return new JsonPath(tokenizer.getPath(), filters.toArray(filterCopy));
}
@ -212,7 +213,7 @@ public class JsonPath {
*/
@SuppressWarnings({"unchecked"})
public <T> T read(Object jsonObject) {
return read(JsonProviderFactory.createProvider(), jsonObject);
return read(jsonObject, Configuration.defaultConfiguration());
}
/**
@ -220,22 +221,21 @@ public class JsonPath {
* Note that the document must be identified as either a List or Map by
* the {@link JsonProvider}
*
* @param jsonProvider JsonProvider to use
* @param jsonObject a container Object
* @param configuration configuration to use
* @param <T> expected return type
* @return list of objects matched by the given path
*/
@SuppressWarnings({"unchecked"})
public <T> T read(JsonProvider jsonProvider, Object jsonObject) {
notNull(jsonProvider, "jsonProvider can not be null");
public <T> T read(Object jsonObject, Configuration configuration) {
notNull(jsonObject, "json can not be null");
notNull(configuration, "configuration can not be null");
if (this.getPath().equals("$")) {
//This path only references the whole object. No need to do any work here...
return (T) jsonObject;
}
if (!jsonProvider.isContainer(jsonObject)) {
if (!configuration.getProvider().isContainer(jsonObject)) {
throw new IllegalArgumentException("Invalid container object");
}
@ -253,12 +253,13 @@ public class JsonPath {
LOG.debug("Applying filter: " + filter + " to " + result);
}
result = filter.filter(result, jsonProvider, contextFilters, inArrayContext);
result = filter.filter(result, configuration, contextFilters, inArrayContext);
//TODO: finalize behaviour
/*
if(result == null && !pathToken.isEndToken()){
throw new PathNotFoundException("AAAAAA");
throw new PathNotFoundException("Path token: " + pathToken.getFragment() + " not found in json");
}
*/
if (!inArrayContext) {
inArrayContext = filter.isArrayFilter();
@ -276,23 +277,23 @@ public class JsonPath {
*/
@SuppressWarnings({"unchecked"})
public <T> T read(String json) {
return read(JsonProviderFactory.createProvider(), json);
return read(json, Configuration.defaultConfiguration());
}
/**
* Applies this JsonPath to the provided json string
*
* @param jsonProvider JsonProvider to use
* @param json a json string
* @param configuration configuration to use
* @param <T> expected return type
* @return list of objects matched by the given path
*/
@SuppressWarnings({"unchecked"})
public <T> T read(JsonProvider jsonProvider, String json) {
notNull(jsonProvider, "jsonProvider can not be null");
public <T> T read(String json, Configuration configuration) {
notEmpty(json, "json can not be null or empty");
notNull(configuration, "jsonProvider can not be null");
return read(jsonProvider, jsonProvider.parse(json));
return read(configuration.getProvider().parse(json), configuration);
}
/**
@ -305,27 +306,27 @@ public class JsonPath {
*/
@SuppressWarnings({"unchecked"})
public <T> T read(URL jsonURL) throws IOException {
return read(JsonProviderFactory.createProvider(), jsonURL);
return read(jsonURL, Configuration.defaultConfiguration());
}
/**
* Applies this JsonPath to the provided json URL
*
* @param jsonProvider JsonProvider to use
* @param jsonURL url to read from
* @param configuration configuration to use
* @param <T> expected return type
* @return list of objects matched by the given path
* @throws IOException
*/
@SuppressWarnings({"unchecked"})
public <T> T read(JsonProvider jsonProvider, URL jsonURL) throws IOException {
notNull(jsonProvider, "jsonProvider can not be null");
public <T> T read(URL jsonURL, Configuration configuration) throws IOException {
notNull(jsonURL, "json URL can not be null");
notNull(configuration, "jsonProvider can not be null");
InputStream in = null;
try {
in = HttpProviderFactory.getProvider().get(jsonURL);
return read(jsonProvider, jsonProvider.parse(in));
return read(configuration.getProvider().parse(in), configuration);
} finally {
IOUtils.closeQuietly(in);
}
@ -341,29 +342,29 @@ public class JsonPath {
*/
@SuppressWarnings({"unchecked"})
public <T> T read(File jsonFile) throws IOException {
return read(JsonProviderFactory.createProvider(), jsonFile);
return read(jsonFile, Configuration.defaultConfiguration());
}
/**
* Applies this JsonPath to the provided json file
*
* @param jsonProvider JsonProvider to use
* @param jsonFile file to read from
* @param configuration configuration to use
* @param <T> expected return type
* @return list of objects matched by the given path
* @throws IOException
*/
@SuppressWarnings({"unchecked"})
public <T> T read(JsonProvider jsonProvider, File jsonFile) throws IOException {
notNull(jsonProvider, "jsonProvider can not be null");
public <T> T read(File jsonFile, Configuration configuration) throws IOException {
notNull(jsonFile, "json file can not be null");
isTrue(jsonFile.exists(), "json file does not exist");
notNull(configuration, "jsonProvider can not be null");
FileInputStream fis = null;
try {
fis = new FileInputStream(jsonFile);
return read(jsonProvider, jsonProvider.parse(fis));
return read(configuration.getProvider().parse(fis), configuration);
} finally {
IOUtils.closeQuietly(fis);
}
@ -391,19 +392,19 @@ public class JsonPath {
/**
* Applies this JsonPath to the provided json input stream
*
* @param jsonProvider JsonProvider to use
* @param jsonInputStream input stream to read from
* @param configuration configuration to use
* @param <T> expected return type
* @return list of objects matched by the given path
* @throws IOException
*/
@SuppressWarnings({"unchecked"})
public <T> T read(JsonProvider jsonProvider, InputStream jsonInputStream) throws IOException {
notNull(jsonProvider, "jsonProvider can not be null");
public <T> T read(InputStream jsonInputStream, Configuration configuration) throws IOException {
notNull(jsonInputStream, "json input stream can not be null");
notNull(configuration, "configuration can not be null");
try {
return read(jsonProvider, jsonProvider.parse(jsonInputStream));
return read(configuration.getProvider().parse(jsonInputStream), configuration);
} finally {
IOUtils.closeQuietly(jsonInputStream);
}
@ -436,73 +437,34 @@ public class JsonPath {
// --------------------------------------------------------
/**
* Creates a new JsonPath and applies it to the provided Json string
* Creates a new JsonPath and applies it to the provided Json object
*
* @param json a json string
* @param json a json object
* @param jsonPath the json path
* @param filters filters to be applied to the filter place holders [?] in the path
* @param <T> expected return type
* @return list of objects matched by the given path
*/
@SuppressWarnings({"unchecked"})
public static <T> T read(String json, String jsonPath, Filter... filters) {
return read(JsonProviderFactory.createProvider(), json, jsonPath, filters);
public static <T> T read(Object json, String jsonPath, Filter... filters) {
return compile(jsonPath, filters).read(json);
}
/**
* Creates a new JsonPath and applies it to the provided Json string
*
* @param jsonProvider JsonProvider to use
* @param json a json string
* @param jsonPath the json path
* @param filters filters to be applied to the filter place holders [?] in the path
* @param <T> expected return type
* @return list of objects matched by the given path
*/
@SuppressWarnings({"unchecked"})
public static <T> T read(JsonProvider jsonProvider, String json, String jsonPath, Filter... filters) {
notNull(jsonProvider, "jsonProvider can not be null");
notEmpty(json, "json can not be null or empty");
notEmpty(jsonPath, "jsonPath can not be null or empty");
return compile(jsonPath, filters).read(jsonProvider, json);
}
/**
* Creates a new JsonPath and applies it to the provided Json object
*
* @param json a json object
* @param json a json string
* @param jsonPath the json path
* @param filters filters to be applied to the filter place holders [?] in the path
* @param <T> expected return type
* @return list of objects matched by the given path
*/
@SuppressWarnings({"unchecked"})
public static <T> T read(Object json, String jsonPath, Filter... filters) {
return read(JsonProviderFactory.createProvider(), json, jsonPath, filters);
}
/**
* Creates a new JsonPath and applies it to the provided Json object
*
* @param jsonProvider JsonProvider to use
* @param json a json object
* @param jsonPath the json path
* @param filters filters to be applied to the filter place holders [?] in the path
* @param <T> expected return type
* @return list of objects matched by the given path
*/
@SuppressWarnings({"unchecked"})
public static <T> T read(JsonProvider jsonProvider, Object json, String jsonPath, Filter... filters) {
notNull(jsonProvider, "jsonProvider can not be null");
notNull(json, "json can not be null");
notNull(jsonPath, "jsonPath can not be null");
return compile(jsonPath, filters).read(jsonProvider, json);
public static <T> T read(String json, String jsonPath, Filter... filters) {
return new JsonReader().parse(json).read(jsonPath, filters);
}
/**
* Creates a new JsonPath and applies it to the provided Json object
*
@ -514,26 +476,7 @@ public class JsonPath {
*/
@SuppressWarnings({"unchecked"})
public static <T> T read(URL jsonURL, String jsonPath, Filter... filters) throws IOException {
return read(JsonProviderFactory.createProvider(), jsonURL, jsonPath, filters);
}
/**
* Creates a new JsonPath and applies it to the provided Json object
*
* @param jsonProvider JsonProvider to use
* @param jsonURL url pointing to json doc
* @param jsonPath the json path
* @param filters filters to be applied to the filter place holders [?] in the path
* @param <T> expected return type
* @return list of objects matched by the given path
*/
@SuppressWarnings({"unchecked"})
public static <T> T read(JsonProvider jsonProvider, URL jsonURL, String jsonPath, Filter... filters) throws IOException {
notNull(jsonProvider, "jsonProvider can not be null");
notNull(jsonURL, "json URL can not be null");
notEmpty(jsonPath, "jsonPath can not be null or empty");
return compile(jsonPath, filters).read(jsonProvider, jsonURL);
return new JsonReader().parse(jsonURL).read(jsonPath, filters);
}
/**
@ -547,26 +490,7 @@ public class JsonPath {
*/
@SuppressWarnings({"unchecked"})
public static <T> T read(File jsonFile, String jsonPath, Filter... filters) throws IOException {
return read(JsonProviderFactory.createProvider(), jsonFile, jsonPath, filters);
}
/**
* Creates a new JsonPath and applies it to the provided Json object
*
* @param jsonProvider JsonProvider to use
* @param jsonFile json file
* @param jsonPath the json path
* @param filters filters to be applied to the filter place holders [?] in the path
* @param <T> expected return type
* @return list of objects matched by the given path
*/
@SuppressWarnings({"unchecked"})
public static <T> T read(JsonProvider jsonProvider, File jsonFile, String jsonPath, Filter... filters) throws IOException {
notNull(jsonProvider, "jsonProvider can not be null");
notNull(jsonFile, "json file can not be null");
notEmpty(jsonPath, "jsonPath can not be null or empty");
return compile(jsonPath, filters).read(jsonProvider, jsonFile);
return new JsonReader().parse(jsonFile).read(jsonPath, filters);
}
/**
@ -580,26 +504,60 @@ public class JsonPath {
*/
@SuppressWarnings({"unchecked"})
public static <T> T read(InputStream jsonInputStream, String jsonPath, Filter... filters) throws IOException {
return read(JsonProviderFactory.createProvider(), jsonInputStream, jsonPath, filters);
return new JsonReader().parse(jsonInputStream).read(jsonPath, filters);
}
/**
* Creates a new JsonPath and applies it to the provided Json object
*
* @param jsonProvider JsonProvider to use
* @param jsonInputStream json input stream
* @param jsonPath the json path
* @param filters filters to be applied to the filter place holders [?] in the path
* @param <T> expected return type
* @return list of objects matched by the given path
*/
//-------
public static ParseContext using(Configuration configuration){
return new JsonReader(configuration);
}
public static ParseContext using(JsonProvider provider){
return new JsonReader(Configuration.builder().jsonProvider(provider).build());
}
public static ReadContext parse(Object json, Configuration configuration) {
return new JsonReader(configuration).parse(json);
}
public static ReadContext parse(Object json) {
return new JsonReader().parse(json);
}
public static ReadContext parse(String json, Configuration configuration){
return new JsonReader(configuration).parse(json);
}
public static ReadContext parse(String json) {
return new JsonReader().parse(json);
}
public static ReadContext parse(InputStream json, Configuration configuration) {
return new JsonReader(configuration).parse(json);
}
public static ReadContext parse(InputStream json) {
return new JsonReader().parse(json);
}
public static ReadContext parse(File json, Configuration configuration) throws IOException {
return new JsonReader(configuration).parse(json);
}
public static ReadContext parse(File json) throws IOException {
return new JsonReader().parse(json);
}
@SuppressWarnings({"unchecked"})
public static <T> T read(JsonProvider jsonProvider, InputStream jsonInputStream, String jsonPath, Filter... filters) throws IOException {
notNull(jsonProvider, "jsonProvider can not be null");
notNull(jsonInputStream, "json input stream can not be null");
notEmpty(jsonPath, "jsonPath can not be null or empty");
public static <T> T read(Configuration configuration, Object json, String path, Filter... filters){
return compile(path, filters).read(json, configuration);
}
return compile(jsonPath, filters).read(jsonProvider, jsonInputStream);
@SuppressWarnings({"unchecked"})
public static <T> T read(Configuration configuration, String json, String path, Filter... filters){
return read(configuration, configuration.getProvider().parse(json), path, filters);
}
}

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

@ -0,0 +1,13 @@
package com.jayway.jsonpath;
/**
* User: kalle
* Date: 8/30/13
* Time: 12:05 PM
*/
public enum Option {
/**
* Throw {@link PathNotFoundException} when JsonPath tries to read a property that does not exists.
*/
THROW_ON_MISSING_PROPERTY
}

20
json-path/src/main/java/com/jayway/jsonpath/ParseContext.java

@ -0,0 +1,20 @@
package com.jayway.jsonpath;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
/**
* User: kalle
* Date: 8/30/13
* Time: 12:03 PM
*/
public interface ParseContext {
ReadContext parse(String json);
ReadContext parse(Object json);
ReadContext parse(InputStream json);
ReadContext parse(File json) throws IOException;
ReadContext parse(URL json) throws IOException;
}

14
json-path/src/main/java/com/jayway/jsonpath/PathNotFoundException.java

@ -1,3 +1,17 @@
/*
* Copyright 2011 the original author or authors.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jayway.jsonpath;
/**

15
json-path/src/main/java/com/jayway/jsonpath/ReadContext.java

@ -0,0 +1,15 @@
package com.jayway.jsonpath;
/**
* User: kalle
* Date: 8/30/13
* Time: 12:03 PM
*/
public interface ReadContext {
Object json();
<T> T read(String path, Filter... filters);
<T> T read(JsonPath path);
}

107
json-path/src/main/java/com/jayway/jsonpath/internal/JsonReader.java

@ -0,0 +1,107 @@
package com.jayway.jsonpath.internal;
import com.jayway.jsonpath.*;
import com.jayway.jsonpath.spi.HttpProviderFactory;
import com.jayway.jsonpath.spi.JsonProvider;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import static org.apache.commons.lang3.Validate.notEmpty;
import static org.apache.commons.lang3.Validate.notNull;
/**
* User: kalle
* Date: 8/30/13
* Time: 12:17 PM
*/
public class JsonReader implements ParseContext, ReadContext {
private final Configuration configuration;
private Object json;
public JsonReader() {
this(Configuration.defaultConfiguration());
}
public JsonReader(JsonProvider jsonProvider) {
this(Configuration.builder().jsonProvider(jsonProvider).build());
}
public JsonReader(Configuration configuration) {
notNull(configuration, "configuration can not be null");
this.configuration = configuration;
}
//------------------------------------------------
//
// ParseContext impl
//
//------------------------------------------------
@Override
public ReadContext parse(Object json) {
notNull(json, "json object can not be null");
this.json = json;
return this;
}
@Override
public ReadContext parse(String json) {
notEmpty(json, "json string can not be null or empty");
this.json = configuration.getProvider().parse(json);
return this;
}
@Override
public ReadContext parse(InputStream json) {
notNull(json, "json input stream can not be null");
this.json = configuration.getProvider().parse(json);
return this;
}
@Override
public ReadContext parse(File json) throws IOException {
notNull(json, "json file can not be null");
FileInputStream fis = null;
try {
fis = new FileInputStream(json);
parse(fis);
} finally {
IOUtils.closeQuietly(fis);
}
return this;
}
@Override
public ReadContext parse(URL json) throws IOException {
notNull(json, "json url can not be null");
InputStream is = HttpProviderFactory.getProvider().get(json);
return parse(is);
}
//------------------------------------------------
//
// ReadContext impl
//
//------------------------------------------------
@Override
public Object json() {
return json;
}
@Override
public <T> T read(String path, Filter... filters) {
notEmpty(path, "path can not be null or empty");
return read(JsonPath.compile(path, filters));
}
@Override
public <T> T read(JsonPath path) {
notNull(path, "path can not be null");
return path.read(json, configuration);
}
}

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

@ -14,10 +14,10 @@
*/
package com.jayway.jsonpath.internal;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.InvalidModelException;
import com.jayway.jsonpath.internal.filter.FilterFactory;
import com.jayway.jsonpath.internal.filter.PathTokenFilter;
import com.jayway.jsonpath.spi.JsonProvider;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -45,12 +45,12 @@ public class PathToken {
return FilterFactory.createFilter(this);
}
public Object filter(Object model, JsonProvider jsonProvider){
return FilterFactory.createFilter(this).filter(model, jsonProvider);
public Object filter(Object model, Configuration configuration){
return FilterFactory.createFilter(this).filter(model, configuration);
}
public Object apply(Object model, JsonProvider jsonProvider){
return FilterFactory.createFilter(this).getRef(model, jsonProvider);
public Object apply(Object model, Configuration configuration){
return FilterFactory.createFilter(this).getRef(model, configuration);
}
public String getFragment() {

1
json-path/src/main/java/com/jayway/jsonpath/internal/PathTokenizer.java

@ -16,7 +16,6 @@ package com.jayway.jsonpath.internal;
import com.jayway.jsonpath.InvalidPathException;
import java.util.Formatter;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

15
json-path/src/main/java/com/jayway/jsonpath/internal/filter/ArrayEvalFilter.java

@ -14,13 +14,13 @@
*/
package com.jayway.jsonpath.internal.filter;
import com.jayway.jsonpath.InvalidPathException;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.Option;
import com.jayway.jsonpath.PathNotFoundException;
import com.jayway.jsonpath.internal.filter.eval.ExpressionEvaluator;
import com.jayway.jsonpath.spi.JsonProvider;
import java.util.Collection;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -41,7 +41,8 @@ public class ArrayEvalFilter extends PathTokenFilter {
@Override
public Object filter(Object obj, JsonProvider jsonProvider) {
public Object filter(Object obj, Configuration configuration) {
JsonProvider jsonProvider = configuration.getProvider();
Iterable<Object> src = null;
try {
src = jsonProvider.toIterable(obj);
@ -50,7 +51,7 @@ public class ArrayEvalFilter extends PathTokenFilter {
}
Object result = jsonProvider.createArray();
for (Object item : src) {
if (isMatch(item, conditionStatement, jsonProvider)) {
if (isMatch(item, conditionStatement, configuration)) {
jsonProvider.setProperty(result, jsonProvider.length(result), item);
}
}
@ -58,7 +59,7 @@ public class ArrayEvalFilter extends PathTokenFilter {
}
@Override
public Object getRef(Object obj, JsonProvider jsonProvider) {
public Object getRef(Object obj, Configuration configuration) {
throw new UnsupportedOperationException("");
}
@ -67,9 +68,9 @@ public class ArrayEvalFilter extends PathTokenFilter {
return true;
}
private boolean isMatch(Object check, ConditionStatement conditionStatement, JsonProvider jsonProvider) {
private boolean isMatch(Object check, ConditionStatement conditionStatement, Configuration configuration) {
try {
Object value = conditionStatement.path.read(check);
Object value = conditionStatement.path.read(check, configuration.options(Option.THROW_ON_MISSING_PROPERTY));
return ExpressionEvaluator.eval(value, conditionStatement.getOperator(), conditionStatement.getExpected());
} catch (PathNotFoundException e){
return false;

15
json-path/src/main/java/com/jayway/jsonpath/internal/filter/ArrayIndexFilter.java

@ -14,7 +14,7 @@
*/
package com.jayway.jsonpath.internal.filter;
import com.jayway.jsonpath.PathNotFoundException;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.spi.JsonProvider;
import java.util.regex.Pattern;
@ -51,7 +51,8 @@ public class ArrayIndexFilter extends PathTokenFilter {
@Override
public Object filter(Object obj, JsonProvider jsonProvider) {
public Object filter(Object obj, Configuration configuration) {
JsonProvider jsonProvider = configuration.getProvider();
Object result = jsonProvider.createArray();
@ -89,7 +90,11 @@ public class ArrayIndexFilter extends PathTokenFilter {
int stop = Integer.parseInt(indexes[1]);
for (int i = start; i < stop; i ++){
jsonProvider.setProperty(result, jsonProvider.length(result), jsonProvider.getProperty(obj, i));
try {
jsonProvider.setProperty(result, jsonProvider.length(result), jsonProvider.getProperty(obj, i));
} catch (IndexOutOfBoundsException e){
break;
}
}
return result;
}
@ -114,10 +119,10 @@ public class ArrayIndexFilter extends PathTokenFilter {
}
@Override
public Object getRef(Object obj, JsonProvider jsonProvider) {
public Object getRef(Object obj, Configuration configuration) {
if(SINGLE_ARRAY_INDEX_PATTERN.matcher(condition).matches()){
String trimmedCondition = trim(condition, 1, 1);
return jsonProvider.getProperty(obj, trimmedCondition);
return configuration.getProvider().getProperty(obj, trimmedCondition);
} else {
throw new UnsupportedOperationException();

10
json-path/src/main/java/com/jayway/jsonpath/internal/filter/ArrayQueryFilter.java

@ -14,8 +14,8 @@
*/
package com.jayway.jsonpath.internal.filter;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.Filter;
import com.jayway.jsonpath.spi.JsonProvider;
import java.util.LinkedList;
@ -29,18 +29,18 @@ public class ArrayQueryFilter extends PathTokenFilter {
}
@Override
public Object filter(Object obj, JsonProvider jsonProvider, LinkedList<Filter> filters, boolean inArrayContext) {
public Object filter(Object obj, Configuration configuration, LinkedList<Filter> filters, boolean inArrayContext) {
Filter filter = filters.poll();
return filter.doFilter(jsonProvider.toIterable(obj), jsonProvider);
return filter.doFilter(configuration.getProvider().toIterable(obj), configuration);
}
@Override
public Object filter(Object obj, JsonProvider jsonProvider) {
public Object filter(Object obj, Configuration configuration) {
throw new UnsupportedOperationException();
}
@Override
public Object getRef(Object obj, JsonProvider jsonProvider) {
public Object getRef(Object obj, Configuration configuration) {
throw new UnsupportedOperationException("");
}

20
json-path/src/main/java/com/jayway/jsonpath/internal/filter/FieldFilter.java

@ -14,7 +14,9 @@
*/
package com.jayway.jsonpath.internal.filter;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.Filter;
import com.jayway.jsonpath.Option;
import com.jayway.jsonpath.PathNotFoundException;
import com.jayway.jsonpath.internal.PathToken;
import com.jayway.jsonpath.spi.JsonProvider;
@ -37,7 +39,8 @@ public class FieldFilter extends PathTokenFilter {
}
@Override
public Object filter(Object obj, JsonProvider jsonProvider, LinkedList<Filter> filters, boolean inArrayContext) {
public Object filter(Object obj, Configuration configuration, LinkedList<Filter> filters, boolean inArrayContext) {
JsonProvider jsonProvider = configuration.getProvider();
if (jsonProvider.isArray(obj)) {
if (!inArrayContext) {
throw new PathNotFoundException("Path '" + condition + "' is being applied to an array. Arrays can not have attributes.");
@ -76,8 +79,11 @@ public class FieldFilter extends PathTokenFilter {
Collection<String> keys = jsonProvider.getPropertyKeys(obj);
if(!keys.contains(condition) && split.length == 1){
//TODO: finalize behaviour
//throw new PathNotFoundException("Path '" + condition + "' not found in the current context:\n" + jsonProvider.toJson(obj));
if(configuration.getOptions().contains(Option.THROW_ON_MISSING_PROPERTY)){
throw new PathNotFoundException("Path '" + condition + "' not found in the current context:\n" + jsonProvider.toJson(obj));
}
if(pathToken.isEndToken()){
return null;
} else {
@ -103,7 +109,9 @@ public class FieldFilter extends PathTokenFilter {
}
public Object filter(Object obj, JsonProvider jsonProvider) {
@Override
public Object filter(Object obj, Configuration configuration) {
JsonProvider jsonProvider = configuration.getProvider();
if (jsonProvider.isArray(obj)) {
return obj;
} else {
@ -112,8 +120,8 @@ public class FieldFilter extends PathTokenFilter {
}
@Override
public Object getRef(Object obj, JsonProvider jsonProvider) {
return filter(obj, jsonProvider);
public Object getRef(Object obj, Configuration configuration) {
return filter(obj, configuration);
}
@Override

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

@ -14,6 +14,7 @@
*/
package com.jayway.jsonpath.internal.filter;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.spi.JsonProvider;
import java.util.Collection;
@ -38,7 +39,8 @@ public class HasFieldFilter extends PathTokenFilter {
}
@Override
public Object filter(Object obj, JsonProvider jsonProvider) {
public Object filter(Object obj, Configuration configuration) {
JsonProvider jsonProvider = configuration.getProvider();
//[?(@.isbn)]
Iterable<Object> src = jsonProvider.toIterable(obj);
@ -56,7 +58,7 @@ public class HasFieldFilter extends PathTokenFilter {
}
@Override
public Object getRef(Object obj, JsonProvider jsonProvider) {
public Object getRef(Object obj, Configuration configuration) {
throw new UnsupportedOperationException();
}

7
json-path/src/main/java/com/jayway/jsonpath/internal/filter/PassthroughFilter.java

@ -14,7 +14,7 @@
*/
package com.jayway.jsonpath.internal.filter;
import com.jayway.jsonpath.spi.JsonProvider;
import com.jayway.jsonpath.Configuration;
/**
* @author Kalle Stenflo
@ -29,12 +29,13 @@ public class PassthroughFilter extends PathTokenFilter {
this.isArrayFilter = isArrayFilter;
}
public Object filter(Object obj, JsonProvider jsonProvider) {
@Override
public Object filter(Object obj, Configuration configuration) {
return obj;
}
@Override
public Object getRef(Object obj, JsonProvider jsonProvider) {
public Object getRef(Object obj, Configuration configuration) {
return obj;
}

10
json-path/src/main/java/com/jayway/jsonpath/internal/filter/PathTokenFilter.java

@ -14,8 +14,8 @@
*/
package com.jayway.jsonpath.internal.filter;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.Filter;
import com.jayway.jsonpath.spi.JsonProvider;
import java.util.LinkedList;
@ -46,13 +46,13 @@ public abstract class PathTokenFilter {
return res;
}
public Object filter(Object obj, JsonProvider jsonProvider, LinkedList<Filter> filters, boolean inArrayContext){
return filter(obj, jsonProvider);
public Object filter(Object obj, Configuration configuration, LinkedList<Filter> filters, boolean inArrayContext){
return filter(obj, configuration);
}
public abstract Object filter(Object obj, JsonProvider jsonProvider);
public abstract Object filter(Object obj, Configuration configuration);
public abstract Object getRef(Object obj, JsonProvider jsonProvider);
public abstract Object getRef(Object obj, Configuration configuration);
public abstract boolean isArrayFilter();

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

@ -15,6 +15,7 @@
package com.jayway.jsonpath.internal.filter;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.spi.JsonProvider;
/**
@ -27,7 +28,8 @@ public class ScanFilter extends PathTokenFilter {
}
@Override
public Object filter(Object obj, JsonProvider jsonProvider) {
public Object filter(Object obj, Configuration configuration) {
JsonProvider jsonProvider = configuration.getProvider();
Object result = jsonProvider.createArray();
scan(obj, result, jsonProvider);
@ -40,7 +42,7 @@ public class ScanFilter extends PathTokenFilter {
}
@Override
public Object getRef(Object obj, JsonProvider jsonProvider) {
public Object getRef(Object obj, Configuration configuration) {
throw new UnsupportedOperationException();
}

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

@ -14,6 +14,7 @@
*/
package com.jayway.jsonpath.internal.filter;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.spi.JsonProvider;
/**
@ -26,7 +27,8 @@ public class WildcardFilter extends PathTokenFilter {
}
@Override
public Object filter(Object obj, JsonProvider jsonProvider) {
public Object filter(Object obj, Configuration configuration) {
JsonProvider jsonProvider = configuration.getProvider();
Object result = jsonProvider.createArray();
if (jsonProvider.isArray(obj)) {
@ -44,7 +46,7 @@ public class WildcardFilter extends PathTokenFilter {
}
@Override
public Object getRef(Object obj, JsonProvider jsonProvider) {
public Object getRef(Object obj, Configuration configuration) {
throw new UnsupportedOperationException();
}

1
json-path/src/main/java/com/jayway/jsonpath/spi/impl/AbstractJsonProvider.java

@ -15,7 +15,6 @@
package com.jayway.jsonpath.spi.impl;
import com.jayway.jsonpath.spi.JsonProvider;
import org.apache.commons.lang3.SerializationUtils;
import java.io.Serializable;

5
json-path/src/test/java/com/jayway/jsonpath/ArraySlicingTest.java

@ -54,15 +54,18 @@ public class ArraySlicingTest {
assertThat(result, Matchers.contains(3, 5, 7, 8));
}
@Test
public void get_between_index_2(){
List<Integer> result = JsonPath.read(JSON_ARRAY, "$[0:1]");
assertThat(result, Matchers.contains(1));
}
@Test(expected = IndexOutOfBoundsException.class)
//@Test(expected = IndexOutOfBoundsException.class)
@Test
public void get_between_index_out_of_bounds(){
List<Integer> result = JsonPath.read(JSON_ARRAY, "$[1:15]");
assertThat(result, Matchers.contains(3, 5, 7, 8, 13, 20));
}
@Test

12
json-path/src/test/java/com/jayway/jsonpath/ExpressionEvalTest.java

@ -10,6 +10,8 @@ import java.math.BigInteger;
import java.util.List;
import java.util.Map;
import static com.jayway.jsonpath.Criteria.where;
import static com.jayway.jsonpath.Filter.filter;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@ -189,10 +191,14 @@ public class ExpressionEvalTest {
@Test
@Ignore //TODO: finalize behaviour
public void nulls_filter() {
List<Map<String, Object>> result = JsonPath.read(DOCUMENT, "$.characters[?(@.offspring == null)]");
List<Map<String, Object>> result = JsonPath.read(DOCUMENT, "$.characters[?]", filter(where("offspring").exists(false)));
System.out.println(result);
assertEquals(1, result.size());
result = JsonPath.read(DOCUMENT, "$.characters[?(@.offspring == null)]");
assertEquals(1, result.size());
result = JsonPath.read(DOCUMENT, "$.characters[?(@.offspring != null)]");
@ -200,6 +206,8 @@ public class ExpressionEvalTest {
result = JsonPath.read(DOCUMENT, "$.characters[?(@.offspring)]");
assertEquals(4, result.size());
}

9
json-path/src/test/java/com/jayway/jsonpath/FilterTest.java

@ -190,7 +190,7 @@ public class FilterTest {
}
@Test
@Ignore //TODO: finalize behaviour
//@Ignore //TODO: finalize behaviour
public void exists_filters_evaluates() throws Exception {
Map<String, Object> check = new HashMap<String, Object>();
check.put("foo", "foo");
@ -202,7 +202,7 @@ public class FilterTest {
assertTrue(filter(where("foo_null").exists(true)).accept(check));
assertFalse(filter(where("foo_null").exists(false)).accept(check));
assertTrue(filter(where("bar").exists(false)).accept(check));
assertTrue(filter(where("bar").exists(false)).accept(check, Configuration.defaultConfiguration()));
assertFalse(filter(where("bar").exists(true)).accept(check));
}
@ -374,7 +374,7 @@ public class FilterTest {
Filter customFilter = new Filter.FilterAdapter() {
@Override
public boolean accept(Object o) {
public boolean accept(Object o, Configuration configuration) {
return 1 == (Integer) o;
}
};
@ -388,18 +388,19 @@ public class FilterTest {
public void filters_can_contain_json_path_expressions() throws Exception {
Object doc = JsonModel.model(DOCUMENT).getJsonObject();
assertTrue(filter(where("$.store..price").gt(10)).accept(doc));
assertFalse(filter(where("$.store..price").gte(100)).accept(doc));
assertTrue(filter(where("$.store..category").ne("fiction")).accept(doc));
assertFalse(filter(where("$.store.bicycle.color").ne("red")).accept(doc));
assertTrue(filter(where("$.store.bicycle.color").ne("blue")).accept(doc));
assertTrue(filter(where("$.store..color").exists(true)).accept(doc));
assertFalse(filter(where("$.store..flavor").exists(true)).accept(doc));
assertTrue(filter(where("$.store..color").regex(Pattern.compile("^r.d$"))).accept(doc));
assertTrue(filter(where("$.store..color").type(String.class)).accept(doc));
assertTrue(filter(where("$.store..price").is(12.99)).accept(doc));
assertFalse(filter(where("$.store..price").is(13.99)).accept(doc));
assertFalse(filter(where("$.store..flavor").exists(true)).accept(doc));
}
@Test

17
json-path/src/test/java/com/jayway/jsonpath/IssuesTest.java

@ -13,6 +13,7 @@ import java.util.List;
import java.util.Map;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.assertThat;
@ -128,12 +129,24 @@ public class IssuesTest {
@Test(expected = PathNotFoundException.class)
@Ignore //TODO: finalize behaviour
public void issue_22() throws Exception {
Configuration configuration = Configuration.builder().options(Option.THROW_ON_MISSING_PROPERTY).build();
//Configuration configuration = Configuration.defaultConfiguration();
String json = "{\"a\":{\"b\":1,\"c\":2}}";
System.out.println(JsonPath.read(configuration, json, "a.d"));
}
@Test
public void issue_22c() throws Exception {
Configuration configuration = Configuration.builder().build();
String json = "{\"a\":{\"b\":1,\"c\":2}}";
System.out.println(JsonPath.read(json, "a.d"));
assertNull(JsonPath.read(configuration, json, "a.d"));
}
@Test
public void issue_22b() throws Exception {
String json = "{\"a\":[{\"b\":1,\"c\":2},{\"b\":5,\"c\":2}]}";

1
json-path/src/test/java/com/jayway/jsonpath/JsonModelTest.java

@ -76,7 +76,6 @@ public class JsonModelTest {
}
@Test
@Ignore //TODO: finalize behaviour
public void has_path_validates() throws Exception {
assertFalse(JsonModel.model(DOCUMENT).hasPath("store.invalid"));
assertFalse(JsonModel.model(DOCUMENT).hasPath("store.book[0].foo"));

5
json-path/src/test/java/com/jayway/jsonpath/PathTest.java

@ -21,6 +21,11 @@ public class PathTest {
return true;
}
@Override
public boolean accept(Object obj, Configuration configuration) {
return true;
}
@Override
public Filter addCriteria(Criteria criteria) {
return this;

43
json-path/src/test/java/com/jayway/jsonpath/reader/ReadConfigurationTest.java

@ -0,0 +1,43 @@
package com.jayway.jsonpath.reader;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.Option;
import com.jayway.jsonpath.spi.JsonProvider;
import com.jayway.jsonpath.spi.JsonProviderFactory;
/**
* User: kalle
* Date: 8/29/13
* Time: 12:09 PM
*/
public class ReadConfigurationTest {
private static JsonProvider provider = JsonProviderFactory.createProvider();
//@Test
public void fluent() {
Configuration configuration = Configuration.defaultConfiguration();
Configuration configuration2 = Configuration.builder()
.jsonProvider(JsonProviderFactory.createProvider())
.options(Option.THROW_ON_MISSING_PROPERTY).build();
JsonProvider jsonProvider = JsonProviderFactory.createProvider();
JsonPath.using(configuration).parse("{}").read("$");
JsonPath.using(jsonProvider).parse("{}").read("$");
JsonPath.parse("{}").read("$");
JsonPath.parse("{}", configuration).read("$");
JsonPath.using(configuration).parse("{}").read("$");
JsonPath.read(configuration, "{}", "$");
}
}
Loading…
Cancel
Save