Browse Source

Gson support (work in progress).

pull/55/head
Kalle Stenflo 10 years ago
parent
commit
7621cd1d43
  1. 6
      json-path/src/main/java/com/jayway/jsonpath/Criteria.java
  2. 2
      json-path/src/main/java/com/jayway/jsonpath/internal/PathCompiler.java
  3. 4
      json-path/src/main/java/com/jayway/jsonpath/internal/compiler/EvaluationContextImpl.java
  4. 4
      json-path/src/main/java/com/jayway/jsonpath/internal/compiler/PathToken.java
  5. 4
      json-path/src/main/java/com/jayway/jsonpath/internal/compiler/ScanPathToken.java
  6. 14
      json-path/src/main/java/com/jayway/jsonpath/internal/spi/converter/DefaultConversionProvider.java
  7. 90
      json-path/src/main/java/com/jayway/jsonpath/internal/spi/converter/GsonConverter.java
  8. 1
      json-path/src/main/java/com/jayway/jsonpath/internal/spi/converter/StringConverter.java
  9. 24
      json-path/src/main/java/com/jayway/jsonpath/internal/spi/json/AbstractJsonProvider.java
  10. 48
      json-path/src/main/java/com/jayway/jsonpath/internal/spi/json/GsonProvider.java
  11. 15
      json-path/src/main/java/com/jayway/jsonpath/spi/json/JsonProvider.java
  12. 3
      json-path/src/test/java/com/jayway/jsonpath/BaseTest.java
  13. 7
      json-path/src/test/java/com/jayway/jsonpath/ConverterTest.java
  14. 19
      json-path/src/test/java/com/jayway/jsonpath/FilterTest.java
  15. 12
      json-path/src/test/java/com/jayway/jsonpath/OptionsTest.java
  16. 2
      json-path/src/test/java/com/jayway/jsonpath/ReturnTypeTest.java
  17. 5
      json-path/src/test/java/com/jayway/jsonpath/old/JsonPathTest.java

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

@ -148,10 +148,10 @@ public class Criteria implements Predicate {
boolean res;
if (configuration.jsonProvider().isArray(actual)) {
int length = configuration.jsonProvider().length(actual);
res = length == size;
res = (length == size);
logger.debug("Array with size {} {} {} => {}", length, name(), size, res);
} else if (actual instanceof String) {
int length = ((String) actual).length();
} else if (configuration.jsonProvider().isString(actual)) {
int length = configuration.jsonProvider().length(actual);
res = length == size;
logger.debug("String with length {} {} {} => {}", length, name(), size, res);
} else {

2
json-path/src/main/java/com/jayway/jsonpath/internal/PathCompiler.java

@ -5,8 +5,8 @@ import com.jayway.jsonpath.Filter;
import com.jayway.jsonpath.InvalidPathException;
import com.jayway.jsonpath.Predicate;
import com.jayway.jsonpath.internal.compiler.ArrayPathToken;
import com.jayway.jsonpath.internal.compiler.PredicatePathToken;
import com.jayway.jsonpath.internal.compiler.PathToken;
import com.jayway.jsonpath.internal.compiler.PredicatePathToken;
import com.jayway.jsonpath.internal.compiler.PropertyPathToken;
import com.jayway.jsonpath.internal.compiler.RootPathToken;
import com.jayway.jsonpath.internal.compiler.ScanPathToken;

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

@ -60,9 +60,9 @@ public class EvaluationContextImpl implements EvaluationContext {
if(resultIndex == 0){
throw new PathNotFoundException("No results for path: " + path.toString());
}
return (T) jsonProvider().unwrap(jsonProvider().getArrayIndex(valueResult, 0));
return (T) jsonProvider().getArrayIndex(valueResult, 0);
}
return (T) jsonProvider().unwrap(valueResult);
return (T)valueResult;
}
@SuppressWarnings("unchecked")

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

@ -27,7 +27,7 @@ public abstract class PathToken {
if(propertyVal == JsonProvider.UNDEFINED){
if(isLeaf()) {
if(ctx.options().contains(Option.DEFAULT_PATH_LEAF_TO_NULL)){
propertyVal = null;
propertyVal = ctx.jsonProvider().createNull();
} else {
if(ctx.options().contains(Option.SUPPRESS_EXCEPTIONS)){
return;
@ -58,7 +58,7 @@ public abstract class PathToken {
Object propertyVal = readObjectProperty(property, model, ctx);
if(propertyVal == JsonProvider.UNDEFINED){
if(ctx.options().contains(Option.DEFAULT_PATH_LEAF_TO_NULL)){
propertyVal = null;
propertyVal = ctx.jsonProvider().createNull();;
} else {
continue;
}

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

@ -1,11 +1,11 @@
package com.jayway.jsonpath.internal.compiler;
import com.jayway.jsonpath.spi.json.JsonProvider;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import com.jayway.jsonpath.spi.json.JsonProvider;
/**
*
*/

14
json-path/src/main/java/com/jayway/jsonpath/internal/spi/converter/DefaultConversionProvider.java

@ -3,19 +3,33 @@ package com.jayway.jsonpath.internal.spi.converter;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.spi.converter.ConversionProvider;
import com.jayway.jsonpath.spi.converter.Converter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
public class DefaultConversionProvider implements ConversionProvider {
private static final Logger logger = LoggerFactory.getLogger(DefaultConversionProvider.class);
private HashMap<Class<?>, HashMap<Class<?>, Converter>> converters = new HashMap<Class<?>, HashMap<Class<?>, Converter>>();
public DefaultConversionProvider(){
addConverters(new NumberConverter());
addConverters(new StringConverter());
addConverters(new DateConverter());
try {
Class.forName("com.google.gson.Gson");
addConverters(new GsonConverter());
} catch (ClassNotFoundException e) {
logger.debug("Gson not found on class path. No converters configured.");
}
}
public void addConverters(ConverterBase converter) {
for (Converter.ConvertiblePair convertible : converter.getConvertibleTypes()) {
if(!converters.containsKey(convertible.getTargetType())){

90
json-path/src/main/java/com/jayway/jsonpath/internal/spi/converter/GsonConverter.java

@ -0,0 +1,90 @@
package com.jayway.jsonpath.internal.spi.converter;
import com.google.gson.JsonArray;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.spi.converter.ConversionException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.Date;
import java.util.List;
import java.util.Map;
public class GsonConverter extends ConverterBase {
public GsonConverter() {
register(JsonPrimitive.class, Integer.class);
register(JsonPrimitive.class, Long.class);
register(JsonPrimitive.class, Float.class);
register(JsonPrimitive.class, Double.class);
register(JsonPrimitive.class, BigDecimal.class);
register(JsonPrimitive.class, BigInteger.class);
register(JsonPrimitive.class, Date.class);
register(JsonPrimitive.class, String.class);
register(JsonPrimitive.class, Boolean.class);
register(JsonArray.class, List.class);
register(JsonArray.class, Map.class);
}
@Override
public Object convert(Object src, Class<?> srcType, Class<?> targetType, Configuration conf) {
assertValidConversion(src, srcType, targetType);
if (src == null || src.getClass().equals(JsonNull.class)) {
return null;
}
if (JsonPrimitive.class.isAssignableFrom(srcType)) {
JsonPrimitive primitive = (JsonPrimitive) src;
if (targetType.equals(Long.class)) {
return primitive.getAsLong();
} else if (targetType.equals(Integer.class)) {
return primitive.getAsInt();
} else if (targetType.equals(BigInteger.class)) {
return primitive.getAsBigInteger();
} else if (targetType.equals(Byte.class)) {
return primitive.getAsByte();
} else if (targetType.equals(BigDecimal.class)) {
return primitive.getAsBigDecimal();
} else if (targetType.equals(Double.class)) {
return primitive.getAsDouble();
} else if (targetType.equals(Float.class)) {
return primitive.getAsFloat();
} else if (targetType.equals(String.class)) {
return primitive.getAsString();
} else if (targetType.equals(Boolean.class)) {
return primitive.getAsBoolean();
} else if (targetType.equals(Date.class)) {
if(primitive.isNumber()){
return new Date(primitive.getAsLong());
} else if(primitive.isString()){
try {
return DateFormat.getInstance().parse(primitive.getAsString());
} catch (ParseException e) {
throw new ConversionException(e);
}
}
}
} else if (JsonObject.class.isAssignableFrom(srcType)) {
} else if (JsonArray.class.isAssignableFrom(srcType)) {
}
return null;
}
}

1
json-path/src/main/java/com/jayway/jsonpath/internal/spi/converter/StringConverter.java

@ -1,7 +1,6 @@
package com.jayway.jsonpath.internal.spi.converter;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.spi.converter.Converter;
public class StringConverter extends ConverterBase {

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

@ -34,11 +34,15 @@ public abstract class AbstractJsonProvider implements JsonProvider {
}
public int compare(Object expected, Object providerParsed) throws ValueCompareException {
if (isNullish(expected) && !isNullish(providerParsed)) {
boolean expNullish = isNullish(expected);
boolean provNullish = isNullish(providerParsed);
if (expNullish && !provNullish) {
return -1;
} else if (!isNullish(expected) && isNullish(providerParsed)) {
} else if (!expNullish && provNullish) {
return 1;
} else if (isNullish(expected) && isNullish(providerParsed)) {
} else if (expNullish && provNullish) {
return 0;
} else if (expected instanceof String && providerParsed instanceof String) {
return ((String) expected).compareTo((String) providerParsed);
@ -64,6 +68,10 @@ public abstract class AbstractJsonProvider implements JsonProvider {
return (o == null || ((o instanceof String) && ("null".equals(o))));
}
@Override
public Object createNull(){
return null;
}
/**
* checks if object is an array
@ -75,6 +83,10 @@ public abstract class AbstractJsonProvider implements JsonProvider {
return (obj instanceof List);
}
public boolean isString(Object obj){
return (obj instanceof String);
}
/**
* Extracts a value from an array
@ -166,8 +178,12 @@ public abstract class AbstractJsonProvider implements JsonProvider {
public int length(Object obj) {
if (isArray(obj)) {
return ((List) obj).size();
} else if (isMap(obj)){
return getPropertyKeys(obj).size();
} else if(obj instanceof String){
return ((String)obj).length();
}
return getPropertyKeys(obj).size();
throw new RuntimeException("length operation can not applied to " + obj!=null?obj.getClass().getName():"null");
}
/**

48
json-path/src/main/java/com/jayway/jsonpath/internal/spi/json/GsonProvider.java

@ -7,6 +7,7 @@ import com.google.gson.JsonArray;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonParser;
@ -46,11 +47,13 @@ public class GsonProvider extends AbstractJsonProvider {
JsonElement element = (JsonElement) providerParsed;
if (isNullish(expected) && !element.isJsonNull()) {
boolean nullish = isNullish(expected);
if (nullish && !element.isJsonNull()) {
return -1;
} else if (!isNullish(expected) && element.isJsonNull()) {
} else if (!nullish && element.isJsonNull()) {
return 1;
} else if (isNullish(expected) && element.isJsonNull()) {
} else if (nullish && element.isJsonNull()) {
return 0;
}
if(element.isJsonPrimitive()){
@ -175,6 +178,12 @@ public class GsonProvider extends AbstractJsonProvider {
return obj.toString();
}
@Override
public Object createNull(){
return JsonNull.INSTANCE;
}
@Override
public Object createMap() {
return new JsonObject();
@ -190,6 +199,17 @@ public class GsonProvider extends AbstractJsonProvider {
return (obj instanceof JsonArray);
}
public boolean isString(Object obj){
if(obj == null) {
return false;
}
JsonElement element = toJsonElement(obj);
if(element.isJsonPrimitive()){
return element.getAsJsonPrimitive().isString();
}
return false;
}
@Override
public Object getArrayIndex(Object obj, int idx) {
return toJsonArray(obj).get(idx);
@ -209,7 +229,7 @@ public class GsonProvider extends AbstractJsonProvider {
@Override
public void setProperty(Object obj, Object key, Object value) {
if (isMap(obj))
toJsonObject(obj).add(key.toString(), toJsonElement(value));
toJsonObject(obj).add(key.toString(), createJsonElement(value));
else {
JsonArray array = toJsonArray(obj);
int index;
@ -219,9 +239,9 @@ public class GsonProvider extends AbstractJsonProvider {
index = array.size();
}
if (index == array.size()) {
array.add(toJsonElement(value));
array.add(createJsonElement(value));
} else {
array.set(index, toJsonElement(value));
array.set(index, createJsonElement(value));
}
}
}
@ -244,9 +264,17 @@ public class GsonProvider extends AbstractJsonProvider {
public int length(Object obj) {
if (isArray(obj)) {
return toJsonArray(obj).size();
} else {
} else if(isMap(obj)){
return toJsonObject(obj).entrySet().size();
} else {
if(obj instanceof JsonElement){
JsonElement element = toJsonElement(obj);
if(element.isJsonPrimitive()){
return element.toString().length();
}
}
}
throw new RuntimeException("length operation can not applied to " + obj!=null?obj.getClass().getName():"null");
}
@Override
@ -263,7 +291,7 @@ public class GsonProvider extends AbstractJsonProvider {
}
}
private JsonElement toJsonElement(Object o) {
private JsonElement createJsonElement(Object o) {
return gson.toJsonTree(o);
}
@ -275,6 +303,10 @@ public class GsonProvider extends AbstractJsonProvider {
return (JsonObject) o;
}
private JsonElement toJsonElement(Object o) {
return (JsonElement) o;
}
public static class NumberTypeAdapter
implements JsonSerializer<Number>, JsonDeserializer<Number>,

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

@ -37,6 +37,8 @@ public interface JsonProvider {
String toJson(Object obj);
Object createNull();
Object createMap();
Object createArray();
@ -50,9 +52,18 @@ public interface JsonProvider {
boolean isArray(Object obj);
/**
* Get the length of an array or object
* checks if object is a string
*
* @param obj an array or an object
* @param obj object to check
* @return true if obj is an array
*/
boolean isString(Object obj);
/**
* Get the length of an json array, json object or a json string
*
* @param obj an array or object or a string
* @return the number of entries in the array or object
*/
int length(Object obj);

3
json-path/src/test/java/com/jayway/jsonpath/BaseTest.java

@ -27,7 +27,8 @@ public class BaseTest {
return new DefaultConversionProvider();
}
});
} */
}
*/

7
json-path/src/test/java/com/jayway/jsonpath/ConverterTest.java

@ -1,9 +1,15 @@
package com.jayway.jsonpath;
import com.jayway.jsonpath.internal.spi.converter.DefaultConversionProvider;
import com.jayway.jsonpath.internal.spi.json.GsonProvider;
import com.jayway.jsonpath.spi.converter.ConversionProvider;
import com.jayway.jsonpath.spi.json.JsonProvider;
import org.junit.Test;
import java.math.BigDecimal;
import java.util.Date;
import java.util.EnumSet;
import java.util.Set;
import static com.jayway.jsonpath.JsonPath.parse;
import static java.util.Collections.singletonMap;
@ -11,6 +17,7 @@ import static org.assertj.core.api.Assertions.assertThat;
public class ConverterTest extends BaseTest {
@Test
public void an_Integer_can_be_converted_to_a_Long() {
assertThat(parse("{\"val\": 1}").read("val", Long.class)).isEqualTo(1L);

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

@ -12,26 +12,7 @@ import static org.assertj.core.api.Assertions.assertThat;
public class FilterTest extends BaseTest {
/*
static {
Configuration.setDefaults(new Configuration.Defaults() {
@Override
public JsonProvider jsonProvider() {
return new GsonProvider();
}
@Override
public Set<Option> options() {
return EnumSet.noneOf(Option.class);
}
@Override
public ConversionProvider conversionProvider() {
return new DefaultConversionProvider();
}
});
}
*/
Object json = Configuration.defaultConfiguration().jsonProvider().parse(
"{" +
" \"int-key\" : 1, " +

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

@ -20,7 +20,7 @@ public class OptionsTest extends BaseTest {
Configuration conf = Configuration.defaultConfiguration();
assertThat(using(conf).parse(singletonMap("foo", "bar")).read("$.baz")).isNull();
assertThat(using(conf).parse("{\"foo\" : \"bar\"}").read("$.baz")).isNull();
}
@Test
@ -28,7 +28,7 @@ public class OptionsTest extends BaseTest {
Configuration conf = Configuration.builder().options(DEFAULT_PATH_LEAF_TO_NULL).build();
assertThat(using(conf).parse("{\"foo\" : \"bar\"}").read("$.baz")).isNull();
assertThat(using(conf).parse("{\"foo\" : \"bar\"}").read("$.baz", Object.class)).isNull();
}
@Test
@ -36,7 +36,7 @@ public class OptionsTest extends BaseTest {
Configuration conf = Configuration.defaultConfiguration();
assertThat(using(conf).parse(singletonMap("foo", "bar")).read("$.foo")).isInstanceOf(String.class);
assertThat(using(conf).parse("{\"foo\" : \"bar\"}").read("$.foo")).isInstanceOf(String.class);
}
@Test
@ -44,21 +44,21 @@ public class OptionsTest extends BaseTest {
Configuration conf = Configuration.builder().options(ALWAYS_RETURN_LIST).build();
assertThat(using(conf).parse(singletonMap("foo", "bar")).read("$.foo")).isInstanceOf(List.class);
assertThat(using(conf).parse("{\"foo\" : \"bar\"}").read("$.foo")).isInstanceOf(List.class);
}
@Test
public void a_path_evaluation_is_returned_as_VALUE_by_default() {
Configuration conf = Configuration.defaultConfiguration();
assertThat(using(conf).parse(singletonMap("foo", "bar")).read("$.foo")).isEqualTo("bar");
assertThat(using(conf).parse("{\"foo\" : \"bar\"}").read("$.foo")).isEqualTo("bar");
}
@Test
public void a_path_evaluation_can_be_returned_as_PATH_LIST() {
Configuration conf = Configuration.builder().options(AS_PATH_LIST).build();
List<String> pathList = using(conf).parse(singletonMap("foo", "bar")).read("$.foo");
List<String> pathList = using(conf).parse("{\"foo\" : \"bar\"}").read("$.foo");
assertThat(pathList).containsOnly("$['foo']");
}

2
json-path/src/test/java/com/jayway/jsonpath/ReturnTypeTest.java

@ -20,7 +20,7 @@ public class ReturnTypeTest extends BaseTest {
@Test
public void assert_ints_can_be_read() {
assertThat(reader.read("$.int-max-property")).isEqualTo(Integer.MAX_VALUE);
assertThat(reader.read("$.int-max-property", Integer.class)).isEqualTo(Integer.MAX_VALUE);
}
@Test

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

@ -1,5 +1,6 @@
package com.jayway.jsonpath.old;
import com.jayway.jsonpath.BaseTest;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.PathNotFoundException;
@ -16,7 +17,7 @@ import static org.hamcrest.Matchers.hasItems;
import static org.hamcrest.Matchers.hasSize;
import static org.junit.Assert.*;
public class JsonPathTest {
public class JsonPathTest extends BaseTest {
static {
@ -61,7 +62,7 @@ public class JsonPathTest {
" }\n" +
"}";
public final static Object OBJ_DOCUMENT = new JsonSmartJsonProvider().parse(DOCUMENT);
public final static Object OBJ_DOCUMENT = JsonPath.parse(DOCUMENT).json();
private final static String PRODUCT_JSON = "{\n" +

Loading…
Cancel
Save