Browse Source

Applied Gson patch and added Gson converters for List and Map.

pull/55/head
Kalle Stenflo 10 years ago
parent
commit
8708a9c531
  1. 61
      json-path/src/main/java/com/jayway/jsonpath/Criteria.java
  2. 45
      json-path/src/main/java/com/jayway/jsonpath/internal/spi/converter/GsonConverter.java
  3. 46
      json-path/src/main/java/com/jayway/jsonpath/internal/spi/json/AbstractJsonProvider.java
  4. 200
      json-path/src/main/java/com/jayway/jsonpath/internal/spi/json/GsonProvider.java
  5. 13
      json-path/src/main/java/com/jayway/jsonpath/spi/json/JsonProvider.java
  6. 3
      json-path/src/test/java/com/jayway/jsonpath/BaseTest.java

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

@ -2,9 +2,11 @@ package com.jayway.jsonpath;
import com.jayway.jsonpath.internal.Path;
import com.jayway.jsonpath.internal.PathCompiler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedList;
@ -33,7 +35,7 @@ public class Criteria implements Predicate {
EQ {
@Override
boolean eval(Object expected, Object actual, Configuration configuration) {
boolean res = (0 == configuration.jsonProvider().compare(expected, actual));
boolean res = (0 == safeCompare(expected, actual));
logger.debug("[{}] {} [{}] => {}", actual, name(), expected, res);
return res;
}
@ -41,7 +43,7 @@ public class Criteria implements Predicate {
NE {
@Override
boolean eval(Object expected, Object actual, Configuration configuration) {
boolean res = (0 != configuration.jsonProvider().compare(expected, actual));
boolean res = (0 != safeCompare(expected, actual));
logger.debug("[{}] {} [{}] => {}", actual, name(), expected, res);
return res;
}
@ -52,7 +54,7 @@ public class Criteria implements Predicate {
if ((expected == null) ^ (actual == null)) {
return false;
}
boolean res = (0 > configuration.jsonProvider().compare(expected, actual));
boolean res = (0 > safeCompare(expected, actual));
logger.debug("[{}] {} [{}] => {}", actual, name(), expected, res);
return res;
}
@ -63,7 +65,7 @@ public class Criteria implements Predicate {
if ((expected == null) ^ (actual == null)) {
return false;
}
boolean res = (0 >= configuration.jsonProvider().compare(expected, actual));
boolean res = (0 >= safeCompare(expected, actual));
logger.debug("[{}] {} [{}] => {}", actual, name(), expected, res);
return res;
}
@ -74,7 +76,7 @@ public class Criteria implements Predicate {
if ((expected == null) ^ (actual == null)) {
return false;
}
boolean res = (0 < configuration.jsonProvider().compare(expected, actual));
boolean res = (0 < safeCompare(expected, actual));
logger.debug("[{}] {} [{}] => {}", actual, name(), expected, res);
return res;
}
@ -85,7 +87,7 @@ public class Criteria implements Predicate {
if ((expected == null) ^ (actual == null)) {
return false;
}
boolean res = (0 <= configuration.jsonProvider().compare(expected, actual));
boolean res = (0 <= safeCompare(expected, actual));
logger.debug("[{}] {} [{}] => {}", actual, name(), expected, res);
return res;
}
@ -96,7 +98,7 @@ public class Criteria implements Predicate {
boolean res = false;
Collection exps = (Collection) expected;
for (Object exp : exps) {
if (0 == configuration.jsonProvider().compare(exp, actual)) {
if (0 == safeCompare(exp, actual)) {
res = true;
break;
}
@ -123,7 +125,7 @@ public class Criteria implements Predicate {
for (Object exp : exps) {
boolean found = false;
for (Object check : configuration.jsonProvider().toIterable(actual)) {
if (0 == configuration.jsonProvider().compare(exp, check)) {
if (0 == safeCompare(exp, check)) {
found = true;
break;
}
@ -150,8 +152,8 @@ public class Criteria implements Predicate {
int length = configuration.jsonProvider().length(actual);
res = (length == size);
logger.debug("Array with size {} {} {} => {}", length, name(), size, res);
} else if (configuration.jsonProvider().isString(actual)) {
int length = configuration.jsonProvider().length(actual);
} else if (actual instanceof String) {
int length = ((String) actual).length();
res = length == size;
logger.debug("String with length {} {} {} => {}", length, name(), size, res);
} else {
@ -567,14 +569,49 @@ public class Criteria implements Predicate {
return this;
}
private static int safeCompare(Object expected, Object providerParsed) throws ValueCompareException {
boolean expNullish = isNullish(expected);
boolean provNullish = isNullish(providerParsed);
if (expNullish && !provNullish) {
return -1;
} else if (!expNullish && provNullish) {
return 1;
} else if (expNullish && provNullish) {
return 0;
} else if (expected instanceof String && providerParsed instanceof String) {
return ((String) expected).compareTo((String) providerParsed);
} else if (expected instanceof Number && providerParsed instanceof Number) {
return new BigDecimal(expected.toString()).compareTo(new BigDecimal(providerParsed.toString()));
} else if (expected instanceof String && providerParsed instanceof Number) {
return new BigDecimal(expected.toString()).compareTo(new BigDecimal(providerParsed.toString()));
} else if (expected instanceof String && providerParsed instanceof Boolean) {
Boolean e = Boolean.valueOf((String) expected);
Boolean a = (Boolean) providerParsed;
return e.compareTo(a);
} else if (expected instanceof Boolean && providerParsed instanceof Boolean) {
Boolean e = (Boolean) expected;
Boolean a = (Boolean) providerParsed;
return e.compareTo(a);
} else {
logger.debug("Can not compare a {} with a {}", expected.getClass().getName(), providerParsed.getClass().getName());
throw new ValueCompareException();
}
}
private static boolean isNullish(Object o) {
return (o == null || ((o instanceof String) && ("null".equals(o))));
}
public static Criteria create(String path, String operator, String expected) {
if (! expected.isEmpty() && expected.charAt(0) == '\'' && expected.charAt(expected.length()-1) == '\'') {
if (!expected.isEmpty() && expected.charAt(0) == '\'' && expected.charAt(expected.length() - 1) == '\'') {
expected = expected.substring(1, expected.length() - 1);
}
Path p = PathCompiler.compile(path);
if("$".equals(path) && (operator == null || operator.isEmpty()) && (expected == null || expected.isEmpty()) ){
if ("$".equals(path) && (operator == null || operator.isEmpty()) && (expected == null || expected.isEmpty())) {
return new Criteria(p, CriteriaType.NE, null);
} else if (operator.isEmpty()) {
return Criteria.where(path).exists(true);

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

@ -1,17 +1,21 @@
package com.jayway.jsonpath.internal.spi.converter;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.internal.spi.json.GsonProvider;
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.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@ -31,9 +35,7 @@ public class GsonConverter extends ConverterBase {
register(JsonPrimitive.class, Boolean.class);
register(JsonArray.class, List.class);
register(JsonArray.class, Map.class);
register(JsonObject.class, Map.class);
}
@Override
@ -67,6 +69,7 @@ public class GsonConverter extends ConverterBase {
} 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()){
@ -80,9 +83,43 @@ public class GsonConverter extends ConverterBase {
} else if (JsonObject.class.isAssignableFrom(srcType)) {
JsonObject srcObject = (JsonObject) src;
if(targetType.equals(Map.class)){
Map<String, Object> targetMap = new LinkedHashMap<String, Object>();
for (Map.Entry<String,JsonElement> entry : srcObject.entrySet()) {
Object val = null;
JsonElement element = entry.getValue();
if(element.isJsonPrimitive()) {
val = GsonProvider.unwrap(element);
} else if(element.isJsonArray()){
val = convert(element, element.getClass(), List.class, conf);
} else if(element.isJsonObject()){
val = convert(element, element.getClass(), Map.class, conf);
} else if(element.isJsonNull()){
val = null;
}
targetMap.put(entry.getKey(), val);
}
return targetMap;
}
} else if (JsonArray.class.isAssignableFrom(srcType)) {
JsonArray srcArray = (JsonArray) src;
if(targetType.equals(List.class)){
List<Object> targetList = new ArrayList<Object>();
for (JsonElement element : srcArray) {
if(element.isJsonPrimitive()) {
targetList.add(GsonProvider.unwrap(element));
} else if(element.isJsonArray()){
targetList.add(convert(element, element.getClass(), List.class, conf));
} else if(element.isJsonObject()){
targetList.add(convert(element, element.getClass(), Map.class, conf));
} else if(element.isJsonNull()){
targetList.add(null);
}
}
return targetList;
}
}
return null;

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

@ -14,12 +14,10 @@
*/
package com.jayway.jsonpath.internal.spi.json;
import com.jayway.jsonpath.ValueCompareException;
import com.jayway.jsonpath.spi.json.JsonProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.List;
import java.util.Map;
@ -28,45 +26,6 @@ public abstract class AbstractJsonProvider implements JsonProvider {
private static final Logger logger = LoggerFactory.getLogger(AbstractJsonProvider.class);
public Object unwrap(Object obj){
return obj;
}
public int compare(Object expected, Object providerParsed) throws ValueCompareException {
boolean expNullish = isNullish(expected);
boolean provNullish = isNullish(providerParsed);
if (expNullish && !provNullish) {
return -1;
} else if (!expNullish && provNullish) {
return 1;
} else if (expNullish && provNullish) {
return 0;
} else if (expected instanceof String && providerParsed instanceof String) {
return ((String) expected).compareTo((String) providerParsed);
} else if (expected instanceof Number && providerParsed instanceof Number) {
return new BigDecimal(expected.toString()).compareTo(new BigDecimal(providerParsed.toString()));
} else if (expected instanceof String && providerParsed instanceof Number) {
return new BigDecimal(expected.toString()).compareTo(new BigDecimal(providerParsed.toString()));
} else if (expected instanceof String && providerParsed instanceof Boolean) {
Boolean e = Boolean.valueOf((String)expected);
Boolean a = (Boolean) providerParsed;
return e.compareTo(a);
} else if (expected instanceof Boolean && providerParsed instanceof Boolean) {
Boolean e = (Boolean) expected;
Boolean a = (Boolean) providerParsed;
return e.compareTo(a);
} else {
logger.debug("Can not compare a {} with a {}", expected.getClass().getName(), providerParsed.getClass().getName());
throw new ValueCompareException();
}
}
private static boolean isNullish(Object o){
return (o == null || ((o instanceof String) && ("null".equals(o))));
}
@Override
public Object createNull(){
return null;
@ -82,11 +41,6 @@ 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
*

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

@ -2,28 +2,19 @@ package com.jayway.jsonpath.internal.spi.json;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.InstanceCreator;
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;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.google.gson.internal.LazilyParsedNumber;
import com.jayway.jsonpath.InvalidJsonException;
import com.jayway.jsonpath.ValueCompareException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
@ -35,58 +26,12 @@ public class GsonProvider extends AbstractJsonProvider {
private static final Logger logger = LoggerFactory.getLogger(GsonProvider.class);
private static final JsonParser parser = new JsonParser();
private static final Gson gson = new GsonBuilder().registerTypeAdapter(Number.class, new NumberTypeAdapter()).create();
private static final Gson gson = new GsonBuilder().create();
static {
//ConverterFactory.registerConverter();
public static Object unwrap(Object o) {
}
public int compare(Object expected, Object providerParsed) throws ValueCompareException {
JsonElement element = (JsonElement) providerParsed;
boolean nullish = isNullish(expected);
if (nullish && !element.isJsonNull()) {
return -1;
} else if (!nullish && element.isJsonNull()) {
return 1;
} else if (nullish && element.isJsonNull()) {
return 0;
}
if(element.isJsonPrimitive()){
JsonPrimitive primitive = element.getAsJsonPrimitive();
if (expected instanceof String && primitive.isString()) {
return ((String) expected).compareTo(primitive.getAsString());
} else if (expected instanceof Number && primitive.isNumber()) {
return new BigDecimal(expected.toString()).compareTo(new BigDecimal(primitive.toString()));
} else if (expected instanceof String && primitive.isNumber()) {
return new BigDecimal(expected.toString()).compareTo(new BigDecimal(primitive.toString()));
} else if (expected instanceof String && primitive.isBoolean()) {
Boolean e = Boolean.valueOf((String)expected);
Boolean a = primitive.getAsBoolean();
return e.compareTo(a);
} else if (expected instanceof Boolean && primitive.isBoolean()) {
Boolean e = (Boolean) expected;
Boolean a = primitive.getAsBoolean();
return e.compareTo(a);
}
}
logger.debug("Can not compare a {} with a {}", expected.getClass().getName(), providerParsed.getClass().getName());
throw new ValueCompareException();
}
private static boolean isNullish(Object o){
return (o == null || ((o instanceof String) && ("null".equals(o))));
}
public Object unwrap(Object o) {
return o;
/*
System.out.println("unwrap " + o);
if (o == null) {
return null;
}
@ -94,46 +39,25 @@ public class GsonProvider extends AbstractJsonProvider {
return o;
}
Object unwrapped = null;
JsonElement e = (JsonElement) o;
if (e.isJsonNull()) {
unwrapped = null;
return null;
} else if (e.isJsonPrimitive()) {
JsonPrimitive p = e.getAsJsonPrimitive();
if (p.isString()) {
unwrapped = p.getAsString();
return p.getAsString();
} else if (p.isBoolean()) {
unwrapped = p.getAsBoolean();
return p.getAsBoolean();
} else if (p.isNumber()) {
unwrapped = unwrapNumber(p.getAsNumber());
}
} else {
//unwrapped = o;
if (e.isJsonArray()) {
JsonArray res = new JsonArray();
for (JsonElement jsonElement : e.getAsJsonArray()) {
if(jsonElement.isJsonPrimitive()){
JsonPrimitive primitive = jsonElement.getAsJsonPrimitive();
if(primitive.isNumber()){
res.add(new JsonPrimitive(unwrapNumber(primitive.getAsNumber())));
}
}
}
unwrapped = res;
//unwrapped = gson.fromJson(e, List.class);
} else {
unwrapped = gson.fromJson(e, Map.class);
return unwrapNumber(p.getAsNumber());
}
}
return unwrapped;
*/
return o;
}
private Number unwrapNumber(Number n){
private static Number unwrapNumber(Number n) {
Number unwrapped;
if (n instanceof LazilyParsedNumber) {
@ -146,11 +70,7 @@ public class GsonProvider extends AbstractJsonProvider {
unwrapped = bigDecimal.longValue();
}
} else {
if (bigDecimal.compareTo(new BigDecimal(Float.MAX_VALUE)) <= 0) {
unwrapped = bigDecimal.floatValue();
} else {
unwrapped = bigDecimal.doubleValue();
}
unwrapped = bigDecimal.doubleValue();
}
} else {
unwrapped = n;
@ -175,7 +95,7 @@ public class GsonProvider extends AbstractJsonProvider {
@Override
public Object createNull(){
public Object createNull() {
return JsonNull.INSTANCE;
}
@ -186,33 +106,24 @@ public class GsonProvider extends AbstractJsonProvider {
@Override
public boolean isArray(Object obj) {
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;
return (obj instanceof JsonArray || obj instanceof List);
}
@Override
public Object getArrayIndex(Object obj, int idx) {
return toJsonArray(obj).get(idx);
System.out.println("getArrayIndex " + obj + " (" + obj.getClass() + ")");
return unwrap(toJsonArray(obj).get(idx));
}
@Override
public Object getMapValue(Object obj, String key) {
Object o = toJsonObject(obj).get(key);
if (o == null) {
JsonObject jsonObject = toJsonObject(obj);
Object o = jsonObject.get(key);
if (!jsonObject.has(key)) {
return UNDEFINED;
} else {
return o;
return unwrap(o);
}
}
@ -238,11 +149,14 @@ public class GsonProvider extends AbstractJsonProvider {
@Override
public boolean isMap(Object obj) {
return (obj instanceof JsonObject) ;
System.out.println("isMap " + obj + " (" + obj.getClass() + ")");
//return (obj instanceof JsonObject || obj instanceof Map);
return (obj instanceof JsonObject);
}
@Override
public Collection<String> getPropertyKeys(Object obj) {
System.out.println("getPropertyKeys " + obj);
List<String> keys = new ArrayList<String>();
for (Map.Entry<String, JsonElement> entry : toJsonObject(obj).entrySet()) {
keys.add(entry.getKey());
@ -252,30 +166,37 @@ public class GsonProvider extends AbstractJsonProvider {
@Override
public int length(Object obj) {
System.out.println("length " + obj);
if (isArray(obj)) {
return toJsonArray(obj).size();
} else if(isMap(obj)){
} else if (isMap(obj)) {
return toJsonObject(obj).entrySet().size();
} else {
if(obj instanceof JsonElement){
if (obj instanceof JsonElement) {
JsonElement element = toJsonElement(obj);
if(element.isJsonPrimitive()){
if (element.isJsonPrimitive()) {
return element.toString().length();
}
}
}
throw new RuntimeException("length operation can not applied to " + obj!=null?obj.getClass().getName():"null");
throw new RuntimeException("length operation can not applied to " + obj != null ? obj.getClass().getName() : "null");
}
@Override
public Iterable<?> toIterable(Object obj) {
System.out.println("toIterable " + obj + " (" + obj.getClass() + ")");
if (isArray(obj)) {
return toJsonArray(obj);
JsonArray arr = toJsonArray(obj);
List<Object> values = new ArrayList<Object>(arr.size());
for (Object o : arr) {
values.add(unwrap(o));
}
return values;
} else {
List<JsonElement> values = new ArrayList<JsonElement>();
JsonObject jsonObject = toJsonObject(obj);
List<Object> values = new ArrayList<Object>();
for (Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) {
values.add(entry.getValue());
values.add(unwrap(entry.getValue()));
}
return values;
}
@ -296,53 +217,4 @@ public class GsonProvider extends AbstractJsonProvider {
private JsonElement toJsonElement(Object o) {
return (JsonElement) o;
}
public static class NumberTypeAdapter
implements JsonSerializer<Number>, JsonDeserializer<Number>,
InstanceCreator<Number> {
public JsonElement serialize(Number src, Type typeOfSrc, JsonSerializationContext
context) {
return new JsonPrimitive(src);
}
public Number deserialize(JsonElement json, Type typeOfT,
JsonDeserializationContext context)
throws JsonParseException {
Number res = null;
JsonPrimitive jsonPrimitive = json.getAsJsonPrimitive();
if (jsonPrimitive.isNumber()) {
Number n = jsonPrimitive.getAsNumber();
if (n instanceof LazilyParsedNumber) {
LazilyParsedNumber lpn = (LazilyParsedNumber) n;
BigDecimal bigDecimal = new BigDecimal(lpn.toString());
if (bigDecimal.scale() <= 0) {
if (bigDecimal.compareTo(new BigDecimal(Integer.MAX_VALUE)) <= 0) {
res = bigDecimal.intValue();
} else {
res = bigDecimal.longValue();
}
} else {
if (bigDecimal.compareTo(new BigDecimal(Float.MAX_VALUE)) <= 0) {
res = bigDecimal.floatValue();
} else {
res = bigDecimal.doubleValue();
}
}
}
} else {
throw new IllegalStateException("Expected a number field, but was " + json);
}
return res;
}
public Number createInstance(Type type) {
return 1L;
}
}
}

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

@ -24,10 +24,6 @@ public interface JsonProvider {
static final Object UNDEFINED = new Object();
Object unwrap(Object obj);
int compare(Object expected, Object providerParsed) throws ValueCompareException;
Object parse(String json) throws InvalidJsonException;
Object parse(InputStream jsonStream) throws InvalidJsonException;
@ -46,15 +42,6 @@ public interface JsonProvider {
*/
boolean isArray(Object obj);
/**
* checks if object is a string
*
* @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
*

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

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

Loading…
Cancel
Save