diff --git a/json-path/src/main/java/com/jayway/jsonpath/Configuration.java b/json-path/src/main/java/com/jayway/jsonpath/Configuration.java index 9dea0e79..e9a2ceae 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/Configuration.java +++ b/json-path/src/main/java/com/jayway/jsonpath/Configuration.java @@ -15,7 +15,7 @@ package com.jayway.jsonpath; import com.jayway.jsonpath.internal.spi.json.JsonSmartJsonProvider; -import com.jayway.jsonpath.internal.spi.mapper.DefaultMappingProvider; +import com.jayway.jsonpath.internal.spi.mapper.JsonSmartMappingProvider; import com.jayway.jsonpath.spi.json.JsonProvider; import com.jayway.jsonpath.spi.mapper.MappingProvider; import org.slf4j.Logger; @@ -40,7 +40,7 @@ public class Configuration { private static Defaults DEFAULTS = new Defaults() { - private final MappingProvider mappingProvider = new DefaultMappingProvider(); + private final MappingProvider mappingProvider = new JsonSmartMappingProvider(); public JsonProvider jsonProvider() { return new JsonSmartJsonProvider(); diff --git a/json-path/src/main/java/com/jayway/jsonpath/JsonPath.java b/json-path/src/main/java/com/jayway/jsonpath/JsonPath.java index a0153316..617670c6 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/JsonPath.java +++ b/json-path/src/main/java/com/jayway/jsonpath/JsonPath.java @@ -176,7 +176,7 @@ public class JsonPath { if(optAsPathList){ return (T)path.evaluate(jsonObject, jsonObject, configuration).getPath(); } else { - Object res = path.evaluate(jsonObject, jsonObject, configuration).getValue(); + Object res = path.evaluate(jsonObject, jsonObject, configuration).getValue(false); if(optAlwaysReturnList && path.isDefinite()){ Object array = configuration.jsonProvider().createArray(); configuration.jsonProvider().setProperty(array, 0, res); diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/EvaluationContext.java b/json-path/src/main/java/com/jayway/jsonpath/internal/EvaluationContext.java index a6d4bdb9..36d4fa57 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/EvaluationContext.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/EvaluationContext.java @@ -43,7 +43,21 @@ public interface EvaluationContext { */ T getValue(); + /** + * See {@link com.jayway.jsonpath.internal.EvaluationContext#getValue()} + * + * @param unwrap tells th underlying json provider if primitives should be unwrapped + * @param expected return type + * @return evaluation result + */ + T getValue(boolean unwrap); + + /** + * Returns the list of formalized paths that represent the result of the evaluation + * @param + * @return list of paths + */ T getPath(); diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/spi/json/AbstractJsonProvider.java b/json-path/src/main/java/com/jayway/jsonpath/internal/spi/json/AbstractJsonProvider.java index eda49d05..e7ec3d5c 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/spi/json/AbstractJsonProvider.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/spi/json/AbstractJsonProvider.java @@ -46,6 +46,10 @@ public abstract class AbstractJsonProvider implements JsonProvider { * @return the entry at the given index */ public Object getArrayIndex(Object obj, int idx) { + return getArrayIndex(obj, idx, true); + } + + public Object getArrayIndex(Object obj, int idx, boolean unwrap){ return ((List) obj).get(idx); } diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/spi/json/GsonJsonProvider.java b/json-path/src/main/java/com/jayway/jsonpath/internal/spi/json/GsonJsonProvider.java index 9e6e43df..b1c24d24 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/spi/json/GsonJsonProvider.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/spi/json/GsonJsonProvider.java @@ -129,7 +129,17 @@ public class GsonJsonProvider extends AbstractJsonProvider { @Override public Object getArrayIndex(Object obj, int idx) { - return unwrap(toJsonArray(obj).get(idx)); + return getArrayIndex(obj, idx, true); + } + + @Override + public Object getArrayIndex(Object obj, int idx, boolean unwrap){ + if(unwrap){ + return unwrap(toJsonArray(obj).get(idx)); + } + else { + return toJsonArray(obj).get(idx); + } } @Override diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/spi/json/JacksonTreeJsonProvider.java b/json-path/src/main/java/com/jayway/jsonpath/internal/spi/json/JacksonTreeJsonProvider.java new file mode 100644 index 00000000..af98464f --- /dev/null +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/spi/json/JacksonTreeJsonProvider.java @@ -0,0 +1,260 @@ +package com.jayway.jsonpath.internal.spi.json; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.fasterxml.jackson.databind.node.TextNode; +import com.jayway.jsonpath.InvalidJsonException; +import com.jayway.jsonpath.JsonPathException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; + +public class JacksonTreeJsonProvider extends AbstractJsonProvider { + + private static final Logger logger = LoggerFactory.getLogger(JacksonJsonProvider.class); + + private static final ObjectMapper defaultObjectMapper = new ObjectMapper(); + + protected ObjectMapper objectMapper; + + public ObjectMapper getObjectMapper() { + return objectMapper; + } + + /** + * Initialize the JacksonTreeJsonProvider with the default ObjectMapper and ObjectReader + */ + public JacksonTreeJsonProvider() { + this(defaultObjectMapper); + } + + /** + * Initialize the JacksonTreeJsonProvider with a custom ObjectMapper and ObjectReader. + * + * @param objectMapper the ObjectMapper to use + */ + public JacksonTreeJsonProvider(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + } + + @Override + public Object parse(String json) throws InvalidJsonException { + try { + return objectMapper.readTree(json); + } catch (IOException e) { + logger.debug("Invalid JSON: \n" + json); + throw new InvalidJsonException(e); + } + } + + @Override + public Object parse(InputStream jsonStream, String charset) throws InvalidJsonException { + try { + return objectMapper.readTree(new InputStreamReader(jsonStream, charset)); + } catch (IOException e) { + throw new InvalidJsonException(e); + } + } + + @Override + public String toJson(Object obj) { + if (!(obj instanceof JsonNode)) { + throw new JsonPathException("Not a JSON Node"); + } + return toString(); + } + + @Override + public Object createArray() { + return JsonNodeFactory.instance.arrayNode(); + } + + @Override + public Object createMap() { + return JsonNodeFactory.instance.objectNode(); + } + + public static Object unwrap(Object o) { + + if (o == null) { + return null; + } + if (!(o instanceof JsonNode)) { + return o; + } + + JsonNode e = (JsonNode) o; + + if (e.isValueNode()) { + + if (e.isTextual()) { + return e.asText(); + } else if (e.isBoolean()) { + return e.asBoolean(); + } else if (e.isInt()) { + return e.asInt(); + } else if (e.isLong()) { + return e.asLong(); + } else if (e.isBigDecimal()) { + return e.decimalValue(); + } else if (e.isDouble()) { + return e.doubleValue(); + } else if (e.isFloat()) { + return e.floatValue(); + } else if (e.isBigDecimal()) { + return e.decimalValue(); + } else if (e.isNull()) { + return null; + } + } + return o; + } + + + @Override + public boolean isArray(Object obj) { + return (obj instanceof ArrayNode || obj instanceof List); + } + + @Override + public Object getArrayIndex(Object obj, int idx) { + return getArrayIndex(obj, idx, true); + } + + @Override + public Object getArrayIndex(Object obj, int idx, boolean unwrap){ + if(unwrap){ + return unwrap(toJsonArray(obj).get(idx)); + } + else { + return toJsonArray(obj).get(idx); + } + } + + @Override + public void setArrayIndex(Object array, int index, Object newValue) { + if (!isArray(array)) { + throw new UnsupportedOperationException(); + } else { + toJsonArray(array).insert( index, createJsonElement(newValue)); + } + } + + @Override + public Object getMapValue(Object obj, String key) { + ObjectNode jsonObject = toJsonObject(obj); + Object o = jsonObject.get(key); + if (!jsonObject.has(key)) { + return UNDEFINED; + } else { + return unwrap(o); + } + } + + @Override + public void setProperty(Object obj, Object key, Object value) { + if (isMap(obj)) + toJsonObject(obj).put(key.toString(), createJsonElement(value)); + else { + ArrayNode array = toJsonArray(obj); + int index; + if (key != null) { + index = key instanceof Integer ? (Integer) key : Integer.parseInt(key.toString()); + } else { + index = array.size(); + } + if (index == array.size()) { + array.add(createJsonElement(value)); + } else { + array.set(index, createJsonElement(value)); + } + } + } + + + + @SuppressWarnings("unchecked") + public void removeProperty(Object obj, Object key) { + if (isMap(obj)) + toJsonObject(obj).remove(key.toString()); + else { + ArrayNode array = toJsonArray(obj); + int index = key instanceof Integer ? (Integer) key : Integer.parseInt(key.toString()); + array.remove(index); + } + } + + @Override + public boolean isMap(Object obj) { + return (obj instanceof ObjectNode); + } + + @Override + public Collection getPropertyKeys(Object obj) { + List keys = new ArrayList(); + + Iterator iter = toJsonObject(obj).fieldNames(); + while (iter.hasNext()){ + keys.add(iter.next()); + } + return keys; + } + + @Override + public int length(Object obj) { + if (isArray(obj)) { + return toJsonArray(obj).size(); + } else if (isMap(obj)) { + return toJsonObject(obj).size(); + } else { + if (obj instanceof TextNode) { + TextNode element = (TextNode) obj; + return element.size(); + } + } + throw new JsonPathException("length operation can not applied to " + obj != null ? obj.getClass().getName() : "null"); + } + + @Override + public Iterable toIterable(Object obj) { + if (isArray(obj)) { + ArrayNode arr = toJsonArray(obj); + List values = new ArrayList(arr.size()); + for (Object o : arr) { + values.add(unwrap(o)); + } + return values; + } else { + List values = new ArrayList(); + Iterator iter = toJsonObject(obj).elements(); + while (iter.hasNext()){ + values.add(unwrap(iter.next())); + } + return values; + } + } + + private JsonNode createJsonElement(Object o) { + return objectMapper.valueToTree(o); + } + + private ArrayNode toJsonArray(Object o) { + return (ArrayNode) o; + } + + private ObjectNode toJsonObject(Object o) { + return (ObjectNode) o; + } + + +} diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/spi/mapper/DateMapper.java b/json-path/src/main/java/com/jayway/jsonpath/internal/spi/mapper/DateMapper.java deleted file mode 100644 index a6fdd43f..00000000 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/spi/mapper/DateMapper.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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.internal.spi.mapper; - -import com.jayway.jsonpath.Configuration; -import com.jayway.jsonpath.spi.mapper.MappingException; - -import java.text.DateFormat; -import java.text.ParseException; -import java.util.Date; - -public class DateMapper extends MapperBase { - - public DateMapper() { - register(Long.class, Date.class); - register(String.class, Date.class); - } - - @Override - public Object convert(Object src, Class srcType, Class targetType, Configuration conf) { - - assertValidConversion(src, srcType, targetType); - - if(src == null){ - return null; - } - if(Long.class.isAssignableFrom(srcType)){ - return new Date((Long) src); - } - else if(String.class.isAssignableFrom(srcType)){ - try { - return DateFormat.getInstance().parse(src.toString()); - } catch (ParseException e) { - throw new MappingException(e); - } - } - - throw new MappingException("Can not map: " + srcType.getName() + " to: " + targetType.getName()); - } -} diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/spi/mapper/DefaultMappingProvider.java b/json-path/src/main/java/com/jayway/jsonpath/internal/spi/mapper/DefaultMappingProvider.java deleted file mode 100644 index 85cc0627..00000000 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/spi/mapper/DefaultMappingProvider.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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.internal.spi.mapper; - -import com.jayway.jsonpath.Configuration; -import com.jayway.jsonpath.spi.mapper.MappingProvider; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.HashMap; - -public class DefaultMappingProvider implements MappingProvider { - - private static final Logger logger = LoggerFactory.getLogger(DefaultMappingProvider.class); - - private HashMap, HashMap, Mapper>> converters = new HashMap, HashMap, Mapper>>(); - - public DefaultMappingProvider(){ - addMapper(new NumberMapper()); - addMapper(new StringMapper()); - addMapper(new DateMapper()); - } - - protected void addMapper(Mapper converter) { - for (Mapper.ConvertiblePair convertible : converter.getConvertibleTypes()) { - if(!converters.containsKey(convertible.getTargetType())){ - converters.put(convertible.getTargetType(), new HashMap, Mapper>()); - } - converters.get(convertible.getTargetType()).put(convertible.getSourceType(), converter); - } - } - - @Override - public T map(Object source, Class targetType, Configuration configuration) { - if(source == null){ - return null; - } - HashMap, Mapper> targetConverters = converters.get(targetType); - if(targetConverters != null){ - Mapper mapper = targetConverters.get(source.getClass()); - if(mapper != null){ - return (T) mapper.convert(source, source.getClass(), targetType, configuration); - } - mapper = targetConverters.get(Object.class); - if(mapper != null){ - return (T) mapper.convert(source, source.getClass(), targetType, configuration); - } - } - return (T)source; - } -} diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/spi/mapper/Factory.java b/json-path/src/main/java/com/jayway/jsonpath/internal/spi/mapper/Factory.java new file mode 100644 index 00000000..32060b63 --- /dev/null +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/spi/mapper/Factory.java @@ -0,0 +1,6 @@ +package com.jayway.jsonpath.internal.spi.mapper; + +public interface Factory { + + T createInstance(); +} diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/spi/mapper/GsonMapper.java b/json-path/src/main/java/com/jayway/jsonpath/internal/spi/mapper/GsonMapper.java deleted file mode 100644 index 70cc6078..00000000 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/spi/mapper/GsonMapper.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * 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.internal.spi.mapper; - -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.GsonJsonProvider; -import com.jayway.jsonpath.spi.mapper.MappingException; - -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; - -public class GsonMapper extends MapperBase { - - public GsonMapper() { - 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(JsonObject.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 MappingException(e); - } - } - } - - - } else if (JsonObject.class.isAssignableFrom(srcType)) { - JsonObject srcObject = (JsonObject) src; - if(targetType.equals(Map.class)){ - Map targetMap = new LinkedHashMap(); - for (Map.Entry entry : srcObject.entrySet()) { - Object val = null; - JsonElement element = entry.getValue(); - if(element.isJsonPrimitive()) { - val = GsonJsonProvider.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 targetList = new ArrayList(); - for (JsonElement element : srcArray) { - if(element.isJsonPrimitive()) { - targetList.add(GsonJsonProvider.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; - } - } - - throw new MappingException("Can not map: " + srcType.getName() + " to: " + targetType.getName()); - } -} diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/spi/mapper/GsonMappingProvider.java b/json-path/src/main/java/com/jayway/jsonpath/internal/spi/mapper/GsonMappingProvider.java index c2418b2b..1c04ed4c 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/spi/mapper/GsonMappingProvider.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/spi/mapper/GsonMappingProvider.java @@ -14,23 +14,51 @@ */ package com.jayway.jsonpath.internal.spi.mapper; +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.jayway.jsonpath.Configuration; import com.jayway.jsonpath.JsonPathException; import com.jayway.jsonpath.spi.mapper.MappingProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class GsonMappingProvider extends DefaultMappingProvider implements MappingProvider { +public class GsonMappingProvider implements MappingProvider { private static final Logger logger = LoggerFactory.getLogger(GsonMappingProvider.class); + private final Factory factory; + + public GsonMappingProvider(final Gson gson) { + this(new Factory() { + @Override + public Gson createInstance() { + return gson; + } + }); + } + + public GsonMappingProvider(Factory factory) { + this.factory = factory; + } + public GsonMappingProvider() { super(); try { Class.forName("com.google.gson.Gson"); - addMapper(new GsonMapper()); + this.factory = new Factory() { + @Override + public Gson createInstance() { + return new Gson(); + } + }; } catch (ClassNotFoundException e) { logger.error("Gson not found on class path. No converters configured."); throw new JsonPathException("Gson not found on path", e); } } + + @Override + public T map(Object source, Class targetType, Configuration configuration) { + return factory.createInstance().getAdapter(targetType).fromJsonTree((JsonElement) source); + } } diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/spi/mapper/JacksonMappingProvider.java b/json-path/src/main/java/com/jayway/jsonpath/internal/spi/mapper/JacksonMappingProvider.java index a2e09d5b..438573b0 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/spi/mapper/JacksonMappingProvider.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/spi/mapper/JacksonMappingProvider.java @@ -18,13 +18,10 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.jayway.jsonpath.Configuration; import com.jayway.jsonpath.spi.mapper.MappingProvider; -import java.util.HashMap; - public class JacksonMappingProvider implements MappingProvider { private final ObjectMapper objectMapper; - private HashMap, HashMap, Mapper>> converters = new HashMap, HashMap, Mapper>>(); public JacksonMappingProvider() { this(new ObjectMapper()); @@ -33,14 +30,7 @@ public class JacksonMappingProvider implements MappingProvider { public JacksonMappingProvider(ObjectMapper objectMapper) { this.objectMapper = objectMapper; } - public void addMapper(Mapper converter) { - for (Mapper.ConvertiblePair convertible : converter.getConvertibleTypes()) { - if(!converters.containsKey(convertible.getTargetType())){ - converters.put(convertible.getTargetType(), new HashMap, Mapper>()); - } - converters.get(convertible.getTargetType()).put(convertible.getSourceType(), converter); - } - } + @Override @@ -48,13 +38,6 @@ public class JacksonMappingProvider implements MappingProvider { if(source == null){ return null; } - HashMap, Mapper> targetConverters = converters.get(targetType); - if(targetConverters != null){ - Mapper mapper = targetConverters.get(source.getClass()); - if(mapper != null){ - return (T) mapper.convert(source, source.getClass(), targetType, configuration); - } - } return objectMapper.convertValue(source, targetType); } } diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/spi/mapper/JsonSmartMappingProvider.java b/json-path/src/main/java/com/jayway/jsonpath/internal/spi/mapper/JsonSmartMappingProvider.java new file mode 100644 index 00000000..731165b3 --- /dev/null +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/spi/mapper/JsonSmartMappingProvider.java @@ -0,0 +1,210 @@ +/* + * 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.internal.spi.mapper; + +import com.jayway.jsonpath.Configuration; +import com.jayway.jsonpath.spi.mapper.MappingException; +import com.jayway.jsonpath.spi.mapper.MappingProvider; +import net.minidev.json.writer.JsonReader; +import net.minidev.json.writer.JsonReaderI; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.math.BigDecimal; +import java.text.DateFormat; +import java.text.ParseException; +import java.util.Date; + +public class JsonSmartMappingProvider implements MappingProvider { + + private static final Logger logger = LoggerFactory.getLogger(JsonSmartMappingProvider.class); + + private static JsonReader DEFAULT = new JsonReader(); + + static { + DEFAULT.registerReader(Long.class, new LongReader()); + DEFAULT.registerReader(Integer.class, new IntegerReader()); + DEFAULT.registerReader(Double.class, new DoubleReader()); + DEFAULT.registerReader(Float.class, new FloatReader()); + DEFAULT.registerReader(BigDecimal.class, new BigDecimalReader()); + DEFAULT.registerReader(String.class, new StringReader()); + DEFAULT.registerReader(Date.class, new DateReader()); + } + + + private final Factory factory; + + public JsonSmartMappingProvider(final JsonReader jsonReader) { + this(new Factory() { + @Override + public JsonReader createInstance() { + return jsonReader; + } + }); + } + + public JsonSmartMappingProvider(Factory factory) { + this.factory = factory; + } + + public JsonSmartMappingProvider() { + this(DEFAULT); + } + + + + @Override + public T map(Object source, Class targetType, Configuration configuration) { + if(source == null){ + return null; + } + if (targetType.isAssignableFrom(source.getClass())) { + return (T) source; + } + return factory.createInstance().getMapper(targetType).convert(source); + } + + private static class StringReader extends JsonReaderI { + public StringReader() { + super(null); + } + public String convert(Object src) { + if(src == null){ + return null; + } + return src.toString(); + } + } + private static class IntegerReader extends JsonReaderI { + public IntegerReader() { + super(null); + } + public Integer convert(Object src) { + if(src == null){ + return null; + } + if (Long.class.isAssignableFrom(src.getClass())) { + return ((Integer) src).intValue(); + } else if (Double.class.isAssignableFrom(src.getClass())) { + return ((Double) src).intValue(); + } else if (BigDecimal.class.isAssignableFrom(src.getClass())) { + return ((BigDecimal) src).intValue(); + } else if (Float.class.isAssignableFrom(src.getClass())) { + return ((Float) src).intValue(); + } else if (String.class.isAssignableFrom(src.getClass())) { + return Integer.valueOf(src.toString()); + } + throw new MappingException("can not map a " + src.getClass() + " to " + Integer.class.getName()); + } + } + private static class LongReader extends JsonReaderI { + public LongReader() { + super(null); + } + public Long convert(Object src) { + if(src == null){ + return null; + } + if (Integer.class.isAssignableFrom(src.getClass())) { + return ((Integer) src).longValue(); + } else if (Double.class.isAssignableFrom(src.getClass())) { + return ((Double) src).longValue(); + } else if (BigDecimal.class.isAssignableFrom(src.getClass())) { + return ((BigDecimal) src).longValue(); + } else if (Float.class.isAssignableFrom(src.getClass())) { + return ((Float) src).longValue(); + } else if (String.class.isAssignableFrom(src.getClass())) { + return Long.valueOf(src.toString()); + } + throw new MappingException("can not map a " + src.getClass() + " to " + Long.class.getName()); + } + } + private static class DoubleReader extends JsonReaderI { + public DoubleReader() { + super(null); + } + public Double convert(Object src) { + if(src == null){ + return null; + } + if (Integer.class.isAssignableFrom(src.getClass())) { + return ((Integer) src).doubleValue(); + } else if (Long.class.isAssignableFrom(src.getClass())) { + return ((Long) src).doubleValue(); + } else if (BigDecimal.class.isAssignableFrom(src.getClass())) { + return ((BigDecimal) src).doubleValue(); + } else if (Float.class.isAssignableFrom(src.getClass())) { + return ((Float) src).doubleValue(); + } else if (String.class.isAssignableFrom(src.getClass())) { + return Double.valueOf(src.toString()); + } + throw new MappingException("can not map a " + src.getClass() + " to " + Double.class.getName()); + } + } + private static class FloatReader extends JsonReaderI { + public FloatReader() { + super(null); + } + public Float convert(Object src) { + if(src == null){ + return null; + } + if (Integer.class.isAssignableFrom(src.getClass())) { + return ((Integer) src).floatValue(); + } else if (Long.class.isAssignableFrom(src.getClass())) { + return ((Long) src).floatValue(); + } else if (BigDecimal.class.isAssignableFrom(src.getClass())) { + return ((BigDecimal) src).floatValue(); + } else if (Double.class.isAssignableFrom(src.getClass())) { + return ((Double) src).floatValue(); + } else if (String.class.isAssignableFrom(src.getClass())) { + return Float.valueOf(src.toString()); + } + throw new MappingException("can not map a " + src.getClass() + " to " + Float.class.getName()); + } + } + private static class BigDecimalReader extends JsonReaderI { + public BigDecimalReader() { + super(null); + } + public BigDecimal convert(Object src) { + if(src == null){ + return null; + } + return new BigDecimal(src.toString()); + } + } + private static class DateReader extends JsonReaderI { + public DateReader() { + super(null); + } + public Date convert(Object src) { + if(src == null){ + return null; + } + if(Long.class.isAssignableFrom(src.getClass())){ + return new Date((Long) src); + } + else if(String.class.isAssignableFrom(src.getClass())){ + try { + return DateFormat.getInstance().parse(src.toString()); + } catch (ParseException e) { + throw new MappingException(e); + } + } + throw new MappingException("can not map a " + src.getClass() + " to " + Date.class.getName()); + } + } +} diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/spi/mapper/Mapper.java b/json-path/src/main/java/com/jayway/jsonpath/internal/spi/mapper/Mapper.java deleted file mode 100644 index a677308c..00000000 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/spi/mapper/Mapper.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * 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.internal.spi.mapper; - -import com.jayway.jsonpath.Configuration; - -import java.util.Set; - -import static com.jayway.jsonpath.internal.Utils.notNull; - -public interface Mapper { - - Set getConvertibleTypes(); - - Object convert(Object src, Class srcType, Class targetType, Configuration conf); - - - /** - * Holder for a source-to-target class pair. - */ - public static final class ConvertiblePair { - - private final Class sourceType; - - private final Class targetType; - - /** - * Create a new source-to-target pair. - * - * @param sourceType the source type - * @param targetType the target type - */ - public ConvertiblePair(Class sourceType, Class targetType) { - notNull(sourceType, "Source type must not be null"); - notNull(targetType, "Target type must not be null"); - this.sourceType = sourceType; - this.targetType = targetType; - } - - public Class getSourceType() { - return this.sourceType; - } - - public Class getTargetType() { - return this.targetType; - } - - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof ConvertiblePair)) return false; - - ConvertiblePair that = (ConvertiblePair) o; - - if (!sourceType.equals(that.sourceType)) return false; - if (!targetType.equals(that.targetType)) return false; - - return true; - } - - @Override - public int hashCode() { - int result = sourceType.hashCode(); - result = 31 * result + targetType.hashCode(); - return result; - } - - @Override - public String toString() { - return this.sourceType.getName() + " -> " + this.targetType.getName(); - } - } -} \ No newline at end of file diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/spi/mapper/MapperBase.java b/json-path/src/main/java/com/jayway/jsonpath/internal/spi/mapper/MapperBase.java deleted file mode 100644 index 0da5e818..00000000 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/spi/mapper/MapperBase.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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.internal.spi.mapper; - -import com.jayway.jsonpath.spi.mapper.MappingException; - -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - -public abstract class MapperBase implements Mapper { - - private final Set convertiblePairs = new HashSet(); - - protected void register(Class srcType, Class targetType){ - convertiblePairs.add(new ConvertiblePair(srcType, targetType)); - } - - @Override - public Set getConvertibleTypes() { - return Collections.unmodifiableSet(convertiblePairs); - } - - void assertValidConversion(Object src, Class srcType, Class targetType) { - - if (src == null) { - return; - } - - if (!srcType.isAssignableFrom(src.getClass())) { - throw new MappingException("Source: " + src.getClass() + " is not assignable from: " + srcType.getName()); - } - if(!canConvert(srcType, targetType)){ - throw new MappingException("Can not map: " + srcType.getName() + " to: " + targetType.getName()); - } - } - - boolean canConvert(Class srcType, Class targetType){ - return convertiblePairs.contains(new Mapper.ConvertiblePair(srcType, targetType)); - } -} diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/spi/mapper/NumberMapper.java b/json-path/src/main/java/com/jayway/jsonpath/internal/spi/mapper/NumberMapper.java deleted file mode 100644 index ef64e686..00000000 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/spi/mapper/NumberMapper.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * 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.internal.spi.mapper; - -import com.jayway.jsonpath.Configuration; -import com.jayway.jsonpath.spi.mapper.MappingException; - -import java.math.BigDecimal; - -public class NumberMapper extends MapperBase { - - public NumberMapper() { - //to long - register(Integer.class, Long.class); - register(Double.class, Long.class); - register(Float.class, Long.class); - register(BigDecimal.class, Long.class); - register(String.class, Long.class); - - //to int - register(Long.class, Integer.class); - register(Double.class, Integer.class); - register(Float.class, Integer.class); - register(BigDecimal.class, Integer.class); - register(String.class, Integer.class); - - //to double - register(Long.class, Double.class); - register(Integer.class, Double.class); - register(Float.class, Double.class); - register(BigDecimal.class, Double.class); - register(String.class, Double.class); - - //to float - register(Long.class, Float.class); - register(Integer.class, Float.class); - register(Double.class, Float.class); - register(BigDecimal.class, Float.class); - register(String.class, Float.class); - - //to BigDecimal - register(Long.class, BigDecimal.class); - register(Integer.class, BigDecimal.class); - register(Double.class, BigDecimal.class); - register(Float.class, BigDecimal.class); - register(String.class, BigDecimal.class); - } - - @Override - public Object convert(Object src, Class srcType, Class targetType, Configuration conf) { - - assertValidConversion(src, srcType, targetType); - - if (src == null) { - return null; - } - //to long - if(targetType.equals(Long.class)) { - if (Integer.class.isAssignableFrom(srcType)) { - return ((Integer) src).longValue(); - } else if (Double.class.isAssignableFrom(srcType)) { - return ((Double) src).longValue(); - } else if (BigDecimal.class.isAssignableFrom(srcType)) { - return ((BigDecimal) src).longValue(); - } else if (Float.class.isAssignableFrom(srcType)) { - return ((Float) src).longValue(); - } else if (String.class.isAssignableFrom(srcType)) { - return Long.parseLong(src.toString()); - } - } - else if(targetType.equals(Integer.class)) { - //to int - if (Long.class.isAssignableFrom(srcType)) { - return ((Long) src).intValue(); - } else if (Double.class.isAssignableFrom(srcType)) { - return ((Double) src).intValue(); - } else if (BigDecimal.class.isAssignableFrom(srcType)) { - return ((BigDecimal) src).intValue(); - } else if (Float.class.isAssignableFrom(srcType)) { - return ((Float) src).intValue(); - } else if (String.class.isAssignableFrom(srcType)) { - return Integer.parseInt(src.toString()); - } - } - else if(targetType.equals(Double.class)) { - //to double - if (Long.class.isAssignableFrom(srcType)) { - return ((Long) src).doubleValue(); - } else if (Integer.class.isAssignableFrom(srcType)) { - return ((Integer) src).doubleValue(); - } else if (BigDecimal.class.isAssignableFrom(srcType)) { - return ((BigDecimal) src).doubleValue(); - } else if (Float.class.isAssignableFrom(srcType)) { - return ((Float) src).doubleValue(); - } else if (String.class.isAssignableFrom(srcType)) { - return Double.parseDouble(src.toString()); - } - } - else if(targetType.equals(Float.class)) { - //to float - if (Long.class.isAssignableFrom(srcType) && targetType.equals(Float.class)) { - return ((Long) src).floatValue(); - } else if (Integer.class.isAssignableFrom(srcType) && targetType.equals(Float.class)) { - return ((Integer) src).floatValue(); - } else if (BigDecimal.class.isAssignableFrom(srcType) && targetType.equals(Float.class)) { - return ((BigDecimal) src).floatValue(); - } else if (Double.class.isAssignableFrom(srcType) && targetType.equals(Float.class)) { - return ((Double) src).floatValue(); - } else if (String.class.isAssignableFrom(srcType) && targetType.equals(Float.class)) { - return Float.parseFloat(src.toString()); - } - } - else if(targetType.equals(BigDecimal.class)) { - //to BigDecimal - if (Long.class.isAssignableFrom(srcType) && targetType.equals(BigDecimal.class)) { - return new BigDecimal(src.toString()); - } else if (Integer.class.isAssignableFrom(srcType) && targetType.equals(BigDecimal.class)) { - return new BigDecimal(src.toString()); - } else if (Float.class.isAssignableFrom(srcType) && targetType.equals(BigDecimal.class)) { - return new BigDecimal(src.toString()); - } else if (Double.class.isAssignableFrom(srcType) && targetType.equals(BigDecimal.class)) { - return new BigDecimal(src.toString()); - } else if (String.class.isAssignableFrom(srcType) && targetType.equals(BigDecimal.class)) { - return new BigDecimal(src.toString()); - } - } - - - - throw new MappingException("Can not map: " + srcType.getName() + " to: " + targetType.getName()); - } -} \ No newline at end of file diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/spi/mapper/StringMapper.java b/json-path/src/main/java/com/jayway/jsonpath/internal/spi/mapper/StringMapper.java deleted file mode 100644 index 114c0a74..00000000 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/spi/mapper/StringMapper.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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.internal.spi.mapper; - -import com.jayway.jsonpath.Configuration; - -public class StringMapper extends MapperBase { - - public StringMapper() { - register(Object.class, String.class); - } - - @Override - public Object convert(Object src, Class srcType, Class targetType, Configuration conf) { - assertValidConversion(src, srcType, targetType); - - if (src == null) { - return null; - } - return src.toString(); - } - - @Override - boolean canConvert(Class srcType, Class targetType){ - return true; - } -} diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/token/EvaluationContextImpl.java b/json-path/src/main/java/com/jayway/jsonpath/internal/token/EvaluationContextImpl.java index a3dedbec..5928bb1f 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/internal/token/EvaluationContextImpl.java +++ b/json-path/src/main/java/com/jayway/jsonpath/internal/token/EvaluationContextImpl.java @@ -124,11 +124,17 @@ public class EvaluationContextImpl implements EvaluationContext { @SuppressWarnings("unchecked") @Override public T getValue() { + return getValue(true); + } + + @SuppressWarnings("unchecked") + @Override + public T getValue(boolean unwrap) { if (path.isDefinite()) { if(resultIndex == 0){ throw new PathNotFoundException("No results for path: " + path.toString()); } - return (T) jsonProvider().getArrayIndex(valueResult, 0); + return (T) jsonProvider().getArrayIndex(valueResult, 0, unwrap); } return (T)valueResult; } diff --git a/json-path/src/main/java/com/jayway/jsonpath/spi/json/JsonProvider.java b/json-path/src/main/java/com/jayway/jsonpath/spi/json/JsonProvider.java index f691894d..5c559c7a 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/spi/json/JsonProvider.java +++ b/json-path/src/main/java/com/jayway/jsonpath/spi/json/JsonProvider.java @@ -93,7 +93,7 @@ public interface JsonProvider { Collection getPropertyKeys(Object obj); /** - * Extracts a value from an array + * Extracts a value from an array anw unwraps provider specific data type * * @param obj an array * @param idx index @@ -101,6 +101,16 @@ public interface JsonProvider { */ Object getArrayIndex(Object obj, int idx); + /** + * Extracts a value from an array + * + * @param obj an array + * @param idx index + * @param unwrap should provider specific data type be unwrapped + * @return the entry at the given index + */ + Object getArrayIndex(Object obj, int idx, boolean unwrap); + /** * Sets a value in an array * diff --git a/json-path/src/test/java/com/jayway/jsonpath/BaseTest.java b/json-path/src/test/java/com/jayway/jsonpath/BaseTest.java index c9fc7ead..e0a448ee 100644 --- a/json-path/src/test/java/com/jayway/jsonpath/BaseTest.java +++ b/json-path/src/test/java/com/jayway/jsonpath/BaseTest.java @@ -3,6 +3,7 @@ package com.jayway.jsonpath; import com.jayway.jsonpath.internal.Path; import com.jayway.jsonpath.internal.spi.json.GsonJsonProvider; import com.jayway.jsonpath.internal.spi.json.JacksonJsonProvider; +import com.jayway.jsonpath.internal.spi.json.JacksonTreeJsonProvider; import com.jayway.jsonpath.internal.spi.mapper.GsonMappingProvider; import com.jayway.jsonpath.internal.spi.mapper.JacksonMappingProvider; import com.jayway.jsonpath.internal.token.PredicateContextImpl; @@ -23,13 +24,18 @@ public class BaseTest { .jsonProvider(new JacksonJsonProvider()) .build(); + public static final Configuration JACKSON_TREE_CONFIGURATION = Configuration + .builder() + .mappingProvider(new JacksonMappingProvider()) + .jsonProvider(new JacksonTreeJsonProvider()) + .build(); + public static final Configuration JSON_SMART_CONFIGURATION = Configuration.defaultConfiguration(); public static final String JSON_DOCUMENT = "{\n" + " \"string-property\" : \"string-value\", \n" + " \"int-max-property\" : " + Integer.MAX_VALUE + ", \n" + " \"long-max-property\" : " + Long.MAX_VALUE + ", \n" + - " \"long-max-property\" : " + Long.MAX_VALUE + ", \n" + " \"boolean-property\" : true, \n" + " \"null-property\" : null, \n" + " \"int-small-property\" : 1, \n" + diff --git a/json-path/src/test/java/com/jayway/jsonpath/GsonJsonProviderTest.java b/json-path/src/test/java/com/jayway/jsonpath/GsonJsonProviderTest.java new file mode 100644 index 00000000..000af9db --- /dev/null +++ b/json-path/src/test/java/com/jayway/jsonpath/GsonJsonProviderTest.java @@ -0,0 +1,89 @@ +package com.jayway.jsonpath; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import org.junit.Test; + +import static com.jayway.jsonpath.JsonPath.using; +import static org.assertj.core.api.Assertions.assertThat; + +public class GsonJsonProviderTest extends BaseTest { + + @Test + public void json_can_be_parsed() { + JsonObject node = using(GSON_CONFIGURATION).parse(JSON_DOCUMENT).read("$"); + assertThat(node.get("string-property").getAsString()).isEqualTo("string-value"); + } + + @Test + public void strings_are_unwrapped() { + JsonElement node = using(GSON_CONFIGURATION).parse(JSON_DOCUMENT).read("$.string-property"); + String unwrapped = using(GSON_CONFIGURATION).parse(JSON_DOCUMENT).read("$.string-property", String.class); + + assertThat(unwrapped).isEqualTo("string-value"); + assertThat(unwrapped).isEqualTo(node.getAsString()); + } + + @Test + public void ints_are_unwrapped() { + JsonElement node = using(GSON_CONFIGURATION).parse(JSON_DOCUMENT).read("$.int-max-property"); + int unwrapped = using(GSON_CONFIGURATION).parse(JSON_DOCUMENT).read("$.int-max-property", Integer.class); + + assertThat(unwrapped).isEqualTo(Integer.MAX_VALUE); + assertThat(unwrapped).isEqualTo(node.getAsInt()); + } + + @Test + public void longs_are_unwrapped() { + JsonElement node = using(GSON_CONFIGURATION).parse(JSON_DOCUMENT).read("$.long-max-property"); + long val = using(GSON_CONFIGURATION).parse(JSON_DOCUMENT).read("$.long-max-property", Long.class); + + assertThat(val).isEqualTo(Long.MAX_VALUE); + assertThat(val).isEqualTo(node.getAsLong()); + } + + @Test + public void int_to_long_mapping() { + assertThat(using(GSON_CONFIGURATION).parse("{\"val\": 1}").read("val", Long.class)).isEqualTo(1L); + } + + @Test + public void an_Integer_can_be_converted_to_a_Double() { + assertThat(using(GSON_CONFIGURATION).parse("{\"val\": 1}").read("val", Double.class)).isEqualTo(1D); + } + + @Test + public void list_of_numbers() { + JsonArray objs = using(GSON_CONFIGURATION).parse(JSON_DOCUMENT).read("$.store.book[*].display-price"); + + assertThat(objs.iterator()).extracting("asDouble").containsExactly(8.95D, 12.99D, 8.99D, 22.99D); + + } + + @Test + public void an_object_can_be_mapped_to_pojo() { + + String json = "{\n" + + " \"foo\" : \"foo\",\n" + + " \"bar\" : 10,\n" + + " \"baz\" : true\n" + + "}"; + + + FooBarBaz fooBarBaz = JsonPath.using(GSON_CONFIGURATION).parse(json).read("$", FooBarBaz.class); + + assertThat(fooBarBaz.foo).isEqualTo("foo"); + assertThat(fooBarBaz.bar).isEqualTo(10L); + assertThat(fooBarBaz.baz).isEqualTo(true); + + } + + public static class FooBarBaz { + public String foo; + public Long bar; + public boolean baz; + } + + +} diff --git a/json-path/src/test/java/com/jayway/jsonpath/JacksonTreeJsonProviderTest.java b/json-path/src/test/java/com/jayway/jsonpath/JacksonTreeJsonProviderTest.java new file mode 100644 index 00000000..46e91cfa --- /dev/null +++ b/json-path/src/test/java/com/jayway/jsonpath/JacksonTreeJsonProviderTest.java @@ -0,0 +1,56 @@ +package com.jayway.jsonpath; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.junit.Test; + +import static com.jayway.jsonpath.JsonPath.using; +import static org.assertj.core.api.Assertions.assertThat; + +public class JacksonTreeJsonProviderTest extends BaseTest { + + @Test + public void json_can_be_parsed() { + ObjectNode node = using(JACKSON_TREE_CONFIGURATION).parse(JSON_DOCUMENT).read("$"); + assertThat(node.get("string-property").asText()).isEqualTo("string-value"); + } + + @Test + public void strings_are_unwrapped() { + JsonNode node = using(JACKSON_TREE_CONFIGURATION).parse(JSON_DOCUMENT).read("$.string-property"); + String unwrapped = using(JACKSON_TREE_CONFIGURATION).parse(JSON_DOCUMENT).read("$.string-property", String.class); + + assertThat(unwrapped).isEqualTo("string-value"); + assertThat(unwrapped).isEqualTo(node.asText()); + } + + @Test + public void ints_are_unwrapped() { + JsonNode node = using(JACKSON_TREE_CONFIGURATION).parse(JSON_DOCUMENT).read("$.int-max-property"); + int unwrapped = using(JACKSON_TREE_CONFIGURATION).parse(JSON_DOCUMENT).read("$.int-max-property", int.class); + assertThat(unwrapped).isEqualTo(Integer.MAX_VALUE); + assertThat(unwrapped).isEqualTo(node.asInt()); + } + + @Test + public void longs_are_unwrapped() { + JsonNode node = using(JACKSON_TREE_CONFIGURATION).parse(JSON_DOCUMENT).read("$.long-max-property"); + long unwrapped = using(JACKSON_TREE_CONFIGURATION).parse(JSON_DOCUMENT).read("$.long-max-property", long.class); + + assertThat(unwrapped).isEqualTo(Long.MAX_VALUE); + assertThat(unwrapped).isEqualTo(node.asLong()); + } + + + @Test + public void list_of_numbers() { + ArrayNode objs = using(JACKSON_TREE_CONFIGURATION).parse(JSON_DOCUMENT).read("$.store.book[*].display-price"); + + + System.out.println(objs.toString()); + + } + + +} diff --git a/json-path/src/test/java/com/jayway/jsonpath/MapperTest.java b/json-path/src/test/java/com/jayway/jsonpath/MapperTest.java index 8a51c692..023ccc68 100644 --- a/json-path/src/test/java/com/jayway/jsonpath/MapperTest.java +++ b/json-path/src/test/java/com/jayway/jsonpath/MapperTest.java @@ -42,5 +42,4 @@ public class MapperTest extends BaseTest { } - }