diff --git a/json-path/src/main/java/com/jayway/jsonpath/JsonModel.java b/json-path/src/main/java/com/jayway/jsonpath/JsonModel.java index 3e9d4252..d2ef5383 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/JsonModel.java +++ b/json-path/src/main/java/com/jayway/jsonpath/JsonModel.java @@ -126,7 +126,7 @@ public class JsonModel { /** * Prints this JsonModel to standard out */ - public void print(){ + public void print() { String json = toJson(); System.out.println(JsonFormatter.prettyPrint(json)); } @@ -134,30 +134,28 @@ public class JsonModel { /** * Check if this JsonModel has the given definite path * - * @see com.jayway.jsonpath.JsonPath#isPathDefinite() - * * @param jsonPath path to check * @return true if model contains path + * @see com.jayway.jsonpath.JsonPath#isPathDefinite() */ - public boolean hasPath(String jsonPath){ + public boolean hasPath(String jsonPath) { return hasPath(JsonPath.compile(jsonPath)); } /** * Check if this JsonModel has the given definite path * - * @see com.jayway.jsonpath.JsonPath#isPathDefinite() - * * @param jsonPath path to check * @return true if model contains path + * @see com.jayway.jsonpath.JsonPath#isPathDefinite() */ - public boolean hasPath(JsonPath jsonPath){ + public boolean hasPath(JsonPath jsonPath) { isTrue(jsonPath.isPathDefinite(), "hasPath can only be used for definite paths"); try { get(jsonPath); - } catch(InvalidPathException e){ + } catch (InvalidPathException e) { return false; } return true; @@ -219,7 +217,7 @@ public class JsonModel { */ @SuppressWarnings({"unchecked"}) public T get(String jsonPath, Filter... filters) { - return (T) get(JsonPath.compile(jsonPath, filters)); + return get(JsonPath.compile(jsonPath, filters)); } /** @@ -233,7 +231,7 @@ public class JsonModel { public T get(JsonPath jsonPath) { notNull(jsonPath, "jsonPath can not be null"); - return (T) jsonPath.read(jsonObject); + return jsonPath.read(jsonProvider, jsonObject); } // -------------------------------------------------------- @@ -341,7 +339,7 @@ public class JsonModel { */ public String toJson(boolean prettyPrint) { String json = jsonProvider.toJson(jsonObject); - if(prettyPrint) + if (prettyPrint) return JsonFormatter.prettyPrint(json); else return json; @@ -378,10 +376,8 @@ public class JsonModel { * addressed by a definite path. In contrast to a detached model changes on the sub model * will be applied on the source model (the JsonModel from which the sub model was created) * - * * @param jsonPath the absolute path to extract a JsonModel for * @return the new JsonModel - * * @see com.jayway.jsonpath.JsonPath#isPathDefinite() */ public JsonModel getSubModel(String jsonPath) { @@ -393,10 +389,8 @@ public class JsonModel { * addressed by a definite path. In contrast to a detached model changes on the sub model * will be applied on the source model (the JsonModel from which the sub model was created) * - * * @param jsonPath the absolute path to extract a JsonModel for * @return the new JsonModel - * * @see com.jayway.jsonpath.JsonPath#isPathDefinite() */ public JsonModel getSubModel(JsonPath jsonPath) { @@ -424,7 +418,7 @@ public class JsonModel { * source model (the JsonModel from which the sub model was created). * * @param jsonPath the absolute path to extract a JsonModel for - * @param filters filters to expand the path + * @param filters filters to expand the path * @return a detached JsonModel */ public JsonModel getSubModelDetached(String jsonPath, Filter... filters) { @@ -442,7 +436,7 @@ public class JsonModel { public JsonModel getSubModelDetached(JsonPath jsonPath) { notNull(jsonPath, "jsonPath can not be null"); - Object subModel = jsonPath.read(jsonObject); + Object subModel = jsonPath.read(jsonProvider, jsonObject); if (!jsonProvider.isContainer(subModel)) { throw new InvalidModelException("The path " + jsonPath.getPath() + " returned an invalid model " + (subModel != null ? subModel.getClass() : "null")); @@ -498,62 +492,114 @@ public class JsonModel { // -------------------------------------------------------- /** - * Creates a JsonModel - * - * @param json json string + * Creates a JsonModel + * + * @param jsonProvider JsonProvider to use + * @param json json string * @return a new JsonModel */ - public static JsonModel model(String json) { + public static JsonModel model(JsonProvider jsonProvider, String json) { + notNull(jsonProvider, "jsonProvider can not be null"); notEmpty(json, "json can not be null or empty"); - return new JsonModel(json, JsonProviderFactory.createProvider()); + return new JsonModel(json, jsonProvider); } + + /** + * Creates a JsonModel + * + * @param json json string + * @return a new JsonModel + */ + public static JsonModel model(String json) { + return model(JsonProviderFactory.createProvider(), json); + } + public static JsonModel create(String json) { return model(json); } /** - * Creates a JsonModel - * - * @param jsonObject a json container (a {@link Map} or a {@link List}) + * Creates a JsonModel + * + * @param jsonProvider JsonProvider to use + * @param jsonObject a json container (a {@link Map} or a {@link List}) * @return a new JsonModel */ - public static JsonModel model(Object jsonObject) { + public static JsonModel model(JsonProvider jsonProvider, Object jsonObject) { + notNull(jsonProvider, "jsonProvider can not be null"); notNull(jsonObject, "jsonObject can not be null"); + return new JsonModel(jsonObject, jsonProvider); + } + - return new JsonModel(jsonObject, JsonProviderFactory.createProvider()); + /** + * Creates a JsonModel + * + * @param jsonObject a json container (a {@link Map} or a {@link List}) + * @return a new JsonModel + */ + public static JsonModel model(Object jsonObject) { + return model(JsonProviderFactory.createProvider(), jsonObject); } + public static JsonModel create(Object jsonObject) { return model(jsonObject); } /** - * Creates a JsonModel - * + * Creates a JsonModel + * + * @param jsonProvider JsonProvider to use * @param url pointing to a Json document * @return a new JsonModel */ - public static JsonModel model(URL url) throws IOException { + public static JsonModel model(JsonProvider jsonProvider, URL url) throws IOException { + notNull(jsonProvider, "jsonProvider can not be null"); notNull(url, "url can not be null"); - return new JsonModel(url, JsonProviderFactory.createProvider()); + return new JsonModel(url, jsonProvider); + } + + /** + * Creates a JsonModel + * + * @param url pointing to a Json document + * @return a new JsonModel + */ + public static JsonModel model(URL url) throws IOException { + return model(JsonProviderFactory.createProvider(), url); } - public static JsonModel create(URL url) throws IOException { + + public static JsonModel create(URL url) throws IOException { return model(url); } - + /** - * Creates a JsonModel - * + * Creates a JsonModel + * + * @param jsonProvider JsonProvider to use * @param jsonInputStream json document stream * @return a new JsonModel */ - public static JsonModel model(InputStream jsonInputStream) throws IOException { + public static JsonModel model(JsonProvider jsonProvider, InputStream jsonInputStream) throws IOException { + notNull(jsonProvider, "jsonProvider can not be null"); notNull(jsonInputStream, "jsonInputStream can not be null"); - return new JsonModel(jsonInputStream, JsonProviderFactory.createProvider()); + return new JsonModel(jsonInputStream, jsonProvider); } - public static JsonModel create(InputStream jsonInputStream) throws IOException { + + /** + * Creates a JsonModel + * + * @param jsonInputStream json document stream + * @return a new JsonModel + */ + public static JsonModel model(InputStream jsonInputStream) throws IOException { + return model(JsonProviderFactory.createProvider(), jsonInputStream); + } + + public static JsonModel create(InputStream jsonInputStream) throws IOException { return model(jsonInputStream); } @@ -570,8 +616,6 @@ public class JsonModel { throw new IndefinitePathException(jsonPath.getPath()); } - JsonProvider jsonProvider = JsonProviderFactory.createProvider(); - Object modelRef = jsonObject; if (jsonPath.getTokenizer().size() == 1) { @@ -605,7 +649,7 @@ public class JsonModel { if (pathToken.isRootToken()) { if (this instanceof JsonSubModel) { JsonSubModel thisModel = (JsonSubModel) this; - + thisModel.parent.setTargetObject(thisModel.subModelPath, newValue); } else { this.jsonObject = newValue; @@ -631,13 +675,12 @@ public class JsonModel { */ public interface ObjectMappingModelReader { /** - * Converts this JsonModel to the specified class using the configured {@link com.jayway.jsonpath.spi.MappingProvider} - * - * @see MappingProviderFactory - * + * Converts this JsonModel to the specified class using the configured {@link com.jayway.jsonpath.spi.MappingProvider} + * * @param targetClass class to convert the {@link JsonModel} to - * @param template class + * @param template class * @return the mapped model + * @see MappingProviderFactory */ T to(Class targetClass); } @@ -648,9 +691,9 @@ public class JsonModel { public interface ListMappingModelReader { /** * Converts this JsonModel to the a list of objects with the provided class using the configured {@link com.jayway.jsonpath.spi.MappingProvider} - * + * * @param targetClass class to convert the {@link JsonModel} array items to - * @param template class + * @param template class * @return the mapped mode */ List of(Class targetClass); @@ -662,18 +705,18 @@ public class JsonModel { /** * Converts this JsonModel to the a {@link List} of objects with the provided class using the configured {@link com.jayway.jsonpath.spi.MappingProvider} - * + * * @param targetClass class to convert the {@link JsonModel} array items to - * @param template class + * @param template class * @return the mapped mode */ List toListOf(Class targetClass); /** * Converts this JsonModel to the a {@link Set} of objects with the provided class using the configured {@link com.jayway.jsonpath.spi.MappingProvider} - * + * * @param targetClass class to convert the {@link JsonModel} array items to - * @param template class + * @param template class * @return the mapped model */ Set toSetOf(Class targetClass); @@ -681,7 +724,7 @@ public class JsonModel { /** * Object mapping interface used when for root object that can be either a {@link List} or a {@link Map}. - * It's up to the invoker to know what the conversion target can be mapped to. + * It's up to the invoker to know what the conversion target can be mapped to. */ public interface MappingModelReader extends ListMappingModelReader, ObjectMappingModelReader { } @@ -692,7 +735,8 @@ public class JsonModel { public interface ObjectOps { /** - * Returns the operation target + * Returns the operation target + * * @return the operation target */ Map getTarget(); @@ -709,7 +753,8 @@ public class JsonModel { /** * Adds the value to the target map if it is not already present - * @param key the key + * + * @param key the key * @param value the value * @return this {@link ObjectOps} */ @@ -722,6 +767,7 @@ public class JsonModel { /** * Tries to convert the value associated with the key to an {@link Integer} + * * @param key the key * @return converted value */ @@ -729,6 +775,7 @@ public class JsonModel { /** * Tries to convert the value associated with the key to an {@link Long} + * * @param key the key * @return converted value */ @@ -736,6 +783,7 @@ public class JsonModel { /** * Tries to convert the value associated with the key to an {@link Double} + * * @param key the key * @return converted value */ @@ -743,6 +791,7 @@ public class JsonModel { /** * Tries to convert the value associated with the key to an {@link String} + * * @param key the key * @return converted value */ @@ -769,8 +818,9 @@ public class JsonModel { /** * Map the target of this {@link ObjectOps} to the provided class + * * @param targetClass class to convert the target object to - * @param template class + * @param template class * @return the mapped model */ T to(Class targetClass); @@ -783,6 +833,7 @@ public class JsonModel { /** * Returns the operation target + * * @return the operation target */ List getTarget(); @@ -820,8 +871,8 @@ public class JsonModel { * @return this {@link ArrayOps} */ ArrayOps transform(Transformer> transformer); - - + + ArrayOps each(Transformer transformer); /** @@ -984,7 +1035,7 @@ public class JsonModel { public ArrayOps each(Transformer transformer) { List targetObject = getTargetObject(jsonPath, List.class); - for(int i = 0; i < targetObject.size(); i++){ + for (int i = 0; i < targetObject.size(); i++) { targetObject.set(i, transformer.transform(targetObject.get(i))); } return this; 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 036bd795..e69cd649 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/JsonPath.java +++ b/json-path/src/main/java/com/jayway/jsonpath/JsonPath.java @@ -204,9 +204,23 @@ public class JsonPath { */ @SuppressWarnings({"unchecked"}) public T read(Object jsonObject) { - notNull(jsonObject, "json can not be null"); + return read(JsonProviderFactory.createProvider(), jsonObject); + } - JsonProvider jsonProvider = JsonProviderFactory.createProvider(); + /** + * Applies this JsonPath to the provided json document. + * Note that the document must be identified as either a List or Map by + * the {@link JsonProvider} + * + * @param jsonProvider JsonProvider to use + * @param jsonObject a container Object + * @param expected return type + * @return list of objects matched by the given path + */ + @SuppressWarnings({"unchecked"}) + public T read(JsonProvider jsonProvider, Object jsonObject) { + notNull(jsonProvider, "jsonProvider can not be null"); + notNull(jsonObject, "json can not be null"); if(this.getPath().equals("$")){ //This path only references the whole object. No need to do any work here... @@ -244,9 +258,23 @@ public class JsonPath { */ @SuppressWarnings({"unchecked"}) public T read(String json) { + return read(JsonProviderFactory.createProvider(), json); + } + + /** + * Applies this JsonPath to the provided json string + * + * @param jsonProvider JsonProvider to use + * @param json a json string + * @param expected return type + * @return list of objects matched by the given path + */ + @SuppressWarnings({"unchecked"}) + public T read(JsonProvider jsonProvider, String json) { + notNull(jsonProvider, "jsonProvider can not be null"); notEmpty(json, "json can not be null or empty"); - return (T) read(JsonProviderFactory.createProvider().parse(json)); + return read(jsonProvider, jsonProvider.parse(json)); } /** @@ -259,12 +287,27 @@ public class JsonPath { */ @SuppressWarnings({"unchecked"}) public T read(URL jsonURL) throws IOException { + return read(JsonProviderFactory.createProvider(), jsonURL); + } + + /** + * Applies this JsonPath to the provided json URL + * + * @param jsonProvider JsonProvider to use + * @param jsonURL url to read from + * @param expected return type + * @return list of objects matched by the given path + * @throws IOException + */ + @SuppressWarnings({"unchecked"}) + public T read(JsonProvider jsonProvider, URL jsonURL) throws IOException { + notNull(jsonProvider, "jsonProvider can not be null"); notNull(jsonURL, "json URL can not be null"); InputStream in = null; try { in = HttpProviderFactory.getProvider().get(jsonURL); - return (T) read(JsonProviderFactory.createProvider().parse(in)); + return read(jsonProvider, jsonProvider.parse(in)); } finally { IOUtils.closeQuietly(in); } @@ -280,13 +323,29 @@ public class JsonPath { */ @SuppressWarnings({"unchecked"}) public T read(File jsonFile) throws IOException { + return read(JsonProviderFactory.createProvider(), jsonFile); + } + + + /** + * Applies this JsonPath to the provided json file + * + * @param jsonProvider JsonProvider to use + * @param jsonFile file to read from + * @param expected return type + * @return list of objects matched by the given path + * @throws IOException + */ + @SuppressWarnings({"unchecked"}) + public T read(JsonProvider jsonProvider, File jsonFile) throws IOException { + notNull(jsonProvider, "jsonProvider can not be null"); notNull(jsonFile, "json file can not be null"); isTrue(jsonFile.exists(), "json file does not exist"); FileInputStream fis = null; try { fis = new FileInputStream(jsonFile); - return (T) read(JsonProviderFactory.createProvider().parse(fis)); + return read(jsonProvider, jsonProvider.parse(fis)); } finally { IOUtils.closeQuietly(fis); } @@ -305,7 +364,28 @@ public class JsonPath { notNull(jsonInputStream, "json input stream can not be null"); try { - return (T) read(JsonProviderFactory.createProvider().parse(jsonInputStream)); + return read(JsonProviderFactory.createProvider().parse(jsonInputStream)); + } finally { + IOUtils.closeQuietly(jsonInputStream); + } + } + + /** + * Applies this JsonPath to the provided json input stream + * + * @param jsonProvider JsonProvider to use + * @param jsonInputStream input stream to read from + * @param expected return type + * @return list of objects matched by the given path + * @throws IOException + */ + @SuppressWarnings({"unchecked"}) + public T read(JsonProvider jsonProvider, InputStream jsonInputStream) throws IOException { + notNull(jsonProvider, "jsonProvider can not be null"); + notNull(jsonInputStream, "json input stream can not be null"); + + try { + return read(jsonProvider, jsonProvider.parse(jsonInputStream)); } finally { IOUtils.closeQuietly(jsonInputStream); } @@ -348,10 +428,27 @@ public class JsonPath { */ @SuppressWarnings({"unchecked"}) public static T read(String json, String jsonPath, Filter... filters) { + return read(JsonProviderFactory.createProvider(), json, jsonPath, filters); + } + + + /** + * Creates a new JsonPath and applies it to the provided Json string + * + * @param jsonProvider JsonProvider to use + * @param json a json string + * @param jsonPath the json path + * @param filters filters to be applied to the filter place holders [?] in the path + * @param expected return type + * @return list of objects matched by the given path + */ + @SuppressWarnings({"unchecked"}) + public static T read(JsonProvider jsonProvider, String json, String jsonPath, Filter... filters) { + notNull(jsonProvider, "jsonProvider can not be null"); notEmpty(json, "json can not be null or empty"); notEmpty(jsonPath, "jsonPath can not be null or empty"); - return (T) compile(jsonPath, filters).read(json); + return compile(jsonPath, filters).read(jsonProvider, json); } /** @@ -365,12 +462,28 @@ public class JsonPath { */ @SuppressWarnings({"unchecked"}) public static T read(Object json, String jsonPath, Filter... filters) { + return read(JsonProviderFactory.createProvider(), json, jsonPath, filters); + } + /** + * Creates a new JsonPath and applies it to the provided Json object + * + * @param jsonProvider JsonProvider to use + * @param json a json object + * @param jsonPath the json path + * @param filters filters to be applied to the filter place holders [?] in the path + * @param expected return type + * @return list of objects matched by the given path + */ + @SuppressWarnings({"unchecked"}) + public static T read(JsonProvider jsonProvider, Object json, String jsonPath, Filter... filters) { + notNull(jsonProvider, "jsonProvider can not be null"); notNull(json, "json can not be null"); notNull(jsonPath, "jsonPath can not be null"); - return (T) compile(jsonPath, filters).read(json); + return compile(jsonPath, filters).read(jsonProvider, json); } + /** * Creates a new JsonPath and applies it to the provided Json object * @@ -382,10 +495,26 @@ public class JsonPath { */ @SuppressWarnings({"unchecked"}) public static T read(URL jsonURL, String jsonPath, Filter... filters) throws IOException { + return read(JsonProviderFactory.createProvider(), jsonURL, jsonPath, filters); + } + + /** + * Creates a new JsonPath and applies it to the provided Json object + * + * @param jsonProvider JsonProvider to use + * @param jsonURL url pointing to json doc + * @param jsonPath the json path + * @param filters filters to be applied to the filter place holders [?] in the path + * @param expected return type + * @return list of objects matched by the given path + */ + @SuppressWarnings({"unchecked"}) + public static T read(JsonProvider jsonProvider, URL jsonURL, String jsonPath, Filter... filters) throws IOException { + notNull(jsonProvider, "jsonProvider can not be null"); notNull(jsonURL, "json URL can not be null"); notEmpty(jsonPath, "jsonPath can not be null or empty"); - return (T) compile(jsonPath, filters).read(jsonURL); + return compile(jsonPath, filters).read(jsonProvider, jsonURL); } /** @@ -399,10 +528,26 @@ public class JsonPath { */ @SuppressWarnings({"unchecked"}) public static T read(File jsonFile, String jsonPath, Filter... filters) throws IOException { + return read(JsonProviderFactory.createProvider(), jsonFile, jsonPath, filters); + } + + /** + * Creates a new JsonPath and applies it to the provided Json object + * + * @param jsonProvider JsonProvider to use + * @param jsonFile json file + * @param jsonPath the json path + * @param filters filters to be applied to the filter place holders [?] in the path + * @param expected return type + * @return list of objects matched by the given path + */ + @SuppressWarnings({"unchecked"}) + public static T read(JsonProvider jsonProvider, File jsonFile, String jsonPath, Filter... filters) throws IOException { + notNull(jsonProvider, "jsonProvider can not be null"); notNull(jsonFile, "json file can not be null"); notEmpty(jsonPath, "jsonPath can not be null or empty"); - return (T) compile(jsonPath, filters).read(jsonFile); + return compile(jsonPath, filters).read(jsonProvider, jsonFile); } /** @@ -416,10 +561,26 @@ public class JsonPath { */ @SuppressWarnings({"unchecked"}) public static T read(InputStream jsonInputStream, String jsonPath, Filter... filters) throws IOException { + return read(JsonProviderFactory.createProvider(), jsonInputStream, jsonPath, filters); + } + + /** + * Creates a new JsonPath and applies it to the provided Json object + * + * @param jsonProvider JsonProvider to use + * @param jsonInputStream json input stream + * @param jsonPath the json path + * @param filters filters to be applied to the filter place holders [?] in the path + * @param expected return type + * @return list of objects matched by the given path + */ + @SuppressWarnings({"unchecked"}) + public static T read(JsonProvider jsonProvider, InputStream jsonInputStream, String jsonPath, Filter... filters) throws IOException { + notNull(jsonProvider, "jsonProvider can not be null"); notNull(jsonInputStream, "json input stream can not be null"); notEmpty(jsonPath, "jsonPath can not be null or empty"); - return (T) compile(jsonPath, filters).read(jsonInputStream); + return compile(jsonPath, filters).read(jsonProvider, jsonInputStream); } } diff --git a/json-path/src/main/java/com/jayway/jsonpath/spi/impl/JsonSmartJsonProvider.java b/json-path/src/main/java/com/jayway/jsonpath/spi/impl/JsonSmartJsonProvider.java index 1014e5ff..d93fca3d 100644 --- a/json-path/src/main/java/com/jayway/jsonpath/spi/impl/JsonSmartJsonProvider.java +++ b/json-path/src/main/java/com/jayway/jsonpath/spi/impl/JsonSmartJsonProvider.java @@ -35,8 +35,6 @@ public class JsonSmartJsonProvider extends AbstractJsonProvider { private Mode mode; - private JSONParser parser; - private ContainerFactory containerFactory = ContainerFactory.FACTORY_SIMPLE; public JsonSmartJsonProvider() { @@ -45,7 +43,6 @@ public class JsonSmartJsonProvider extends AbstractJsonProvider { public JsonSmartJsonProvider(Mode mode) { this.mode = mode; - this.parser = new JSONParser(mode.intValue()); } public Map createMap() { @@ -59,7 +56,7 @@ public class JsonSmartJsonProvider extends AbstractJsonProvider { public Object parse(String json) { try { //return parser.parse(json, ContainerFactory.FACTORY_ORDERED); - return parser.parse(json, containerFactory); + return createParser().parse(json, containerFactory); } catch (ParseException e) { throw new InvalidJsonException(e); } @@ -68,7 +65,7 @@ public class JsonSmartJsonProvider extends AbstractJsonProvider { @Override public Object parse(Reader jsonReader) throws InvalidJsonException { try { - return parser.parse(jsonReader, containerFactory); + return createParser().parse(jsonReader, containerFactory); } catch (ParseException e) { throw new InvalidJsonException(e); } @@ -77,7 +74,7 @@ public class JsonSmartJsonProvider extends AbstractJsonProvider { @Override public Object parse(InputStream jsonStream) throws InvalidJsonException { try { - return parser.parse(new InputStreamReader(jsonStream), containerFactory); + return createParser().parse(new InputStreamReader(jsonStream), containerFactory); } catch (ParseException e) { throw new InvalidJsonException(e); } @@ -98,4 +95,8 @@ public class JsonSmartJsonProvider extends AbstractJsonProvider { public Mode getMode() { return mode; } + + private JSONParser createParser(){ + return new JSONParser(mode.intValue()); + } }