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 ef3186e5..373c713a 100644
--- a/json-path/src/main/java/com/jayway/jsonpath/JsonPath.java
+++ b/json-path/src/main/java/com/jayway/jsonpath/JsonPath.java
@@ -15,20 +15,28 @@
package com.jayway.jsonpath;
-import com.jayway.jsonpath.internal.JsonReader;
-import com.jayway.jsonpath.internal.Path;
-import com.jayway.jsonpath.internal.PathCompiler;
-import com.jayway.jsonpath.internal.Utils;
-import com.jayway.jsonpath.spi.http.HttpProviderFactory;
-import com.jayway.jsonpath.spi.json.JsonProvider;
+import static com.jayway.jsonpath.internal.Utils.isTrue;
+import static com.jayway.jsonpath.internal.Utils.notEmpty;
+import static com.jayway.jsonpath.internal.Utils.notNull;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
-import static com.jayway.jsonpath.internal.Utils.*;
+import com.jayway.jsonpath.internal.EvaluationContext;
+import com.jayway.jsonpath.internal.JsonReader;
+import com.jayway.jsonpath.internal.Path;
+import com.jayway.jsonpath.internal.PathCompiler;
+import com.jayway.jsonpath.internal.Utils;
+import com.jayway.jsonpath.spi.http.HttpProviderFactory;
+import com.jayway.jsonpath.spi.json.JsonProvider;
/**
*
@@ -452,7 +460,58 @@ public class JsonPath {
return new JsonReader().parse(jsonInputStream).read(jsonPath, filters);
}
+ //-------------------------
+
+
+ /**
+ * Creates a new JsonPath and applies it to the provided Json object
+ *
+ * @param json a json object
+ * @param jsonPath the json path
+ * @param filters filters to be applied to the filter place holders [?] in the path
+ * @return json object without elemens matched by given path
+ */
+ @SuppressWarnings("rawtypes")
+ public static Map remove(Object json, String jsonPath, Predicate... filters) {
+ return parse(json).remove(jsonPath, Map.class, filters);
+ }
+
+ /**
+ * Creates a new JsonPath and applies it to the provided Json object
+ *
+ * @param json a json string
+ * @param jsonPath the json path
+ * @param filters filters to be applied to the filter place holders [?] in the path
+ * @return list of objects matched by the given path
+ */
+ public static String remove(String json, String jsonPath, Predicate... filters) {
+ return parse(json).remove(jsonPath, String.class, filters);
+ }
+
+ /**
+ * Creates a new JsonPath and applies it to the provided Json object
+ *
+ * @param json url pointing to json doc
+ * @param jsonPath the json path
+ * @param filters filters to be applied to the filter place holders [?] in the path
+ * @return list of objects matched by the given path
+ */
+ public static String remove(URL json, String jsonPath, Predicate... filters) throws IOException {
+ return parse(json).remove(jsonPath, String.class, filters);
+ }
+ /**
+ * Creates a new JsonPath and applies it to the provided Json object
+ *
+ * @param json json file
+ * @param jsonPath the json path
+ * @param filters filters to be applied to the filter place holders [?] in the path
+ * @return list of objects matched by the given path
+ */
+ public static String remove(File json, String jsonPath, Predicate... filters) throws IOException {
+ return parse(json).remove(jsonPath, String.class, filters);
+ }
+
// --------------------------------------------------------
//
// Static Fluent API
@@ -589,4 +648,59 @@ public class JsonPath {
public static ReadContext parse(URL json, Configuration configuration) throws IOException {
return new JsonReader(configuration).parse(json);
}
+
+ private List splitPath(String pathSteps) {
+ List result = new ArrayList();
+ for (String string : pathSteps.split("\\]"))
+ result.add(string.replaceAll("[\\[\\$\\']+", ""));
+ return result;
+ }
+
+ /**
+ * 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 jsonObject a container Object
+ * @param configuration configuration to use
+ * @param Class expected return type
+ * @return json object without elemens matched by the path
+ */
+ @SuppressWarnings("unchecked")
+ public T removeTyped(Object jsonObject, Configuration configuration, Class returnType) {
+ boolean optSuppressExceptions = configuration.containsOption(Option.SUPPRESS_EXCEPTIONS);
+ Object result = jsonObject;
+ try {
+ EvaluationContext evalContext = path.evaluate(jsonObject, jsonObject, configuration);
+ for (String pathSteps : evalContext.getPathList())
+ result = remove(result, splitPath(pathSteps));
+ } catch (RuntimeException e){
+ if(!optSuppressExceptions){
+ throw e;
+ }
+ }
+ if(Map.class.isAssignableFrom(returnType))
+ return (T) result;
+ if(String.class.isAssignableFrom(returnType))
+ return (T) configuration.jsonProvider().toJson(result);
+ throw new RuntimeException("Unknown returnType: "+returnType.getSimpleName());
+ }
+
+ @SuppressWarnings("unchecked")
+ private T remove(T jsonObject, List pathList) {
+ if(jsonObject instanceof Map) {
+ Map map = (Map) jsonObject;
+ Set keys = new HashSet(map.keySet());
+ for (String key : keys) {
+ if(key.equals(pathList.get(0))) {
+ if(pathList.size() > 1)
+ remove(map.get(key), pathList.subList(1, pathList.size()));
+ else
+ map.remove(key);
+ }
+ }
+ return (T) map;
+ }
+ return jsonObject;
+ }
}
diff --git a/json-path/src/main/java/com/jayway/jsonpath/ReadContext.java b/json-path/src/main/java/com/jayway/jsonpath/ReadContext.java
index 5f78a21f..3cfb5184 100644
--- a/json-path/src/main/java/com/jayway/jsonpath/ReadContext.java
+++ b/json-path/src/main/java/com/jayway/jsonpath/ReadContext.java
@@ -14,6 +14,7 @@
*/
package com.jayway.jsonpath;
+
public interface ReadContext {
/**
@@ -84,4 +85,13 @@ public interface ReadContext {
*/
ReadContext withListeners(EvaluationListener... listener);
+ /**
+ * Removes the given path from this context
+ *
+ * @param path path to read
+ * @param filters filters
+ * @param
+ * @return result
+ */
+ T remove(String jsonPath, Class returnType, Predicate... filters);
}
diff --git a/json-path/src/main/java/com/jayway/jsonpath/internal/JsonReader.java b/json-path/src/main/java/com/jayway/jsonpath/internal/JsonReader.java
index df307fe3..4fa260d9 100644
--- a/json-path/src/main/java/com/jayway/jsonpath/internal/JsonReader.java
+++ b/json-path/src/main/java/com/jayway/jsonpath/internal/JsonReader.java
@@ -14,13 +14,8 @@
*/
package com.jayway.jsonpath.internal;
-import com.jayway.jsonpath.Configuration;
-import com.jayway.jsonpath.EvaluationListener;
-import com.jayway.jsonpath.JsonPath;
-import com.jayway.jsonpath.ParseContext;
-import com.jayway.jsonpath.Predicate;
-import com.jayway.jsonpath.ReadContext;
-import com.jayway.jsonpath.spi.http.HttpProviderFactory;
+import static com.jayway.jsonpath.internal.Utils.notEmpty;
+import static com.jayway.jsonpath.internal.Utils.notNull;
import java.io.File;
import java.io.FileInputStream;
@@ -28,8 +23,13 @@ import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
-import static com.jayway.jsonpath.internal.Utils.notEmpty;
-import static com.jayway.jsonpath.internal.Utils.notNull;
+import com.jayway.jsonpath.Configuration;
+import com.jayway.jsonpath.EvaluationListener;
+import com.jayway.jsonpath.JsonPath;
+import com.jayway.jsonpath.ParseContext;
+import com.jayway.jsonpath.Predicate;
+import com.jayway.jsonpath.ReadContext;
+import com.jayway.jsonpath.spi.http.HttpProviderFactory;
public class JsonReader implements ParseContext, ReadContext {
@@ -158,6 +158,16 @@ public class JsonReader implements ParseContext, ReadContext {
return configuration.mappingProvider().map(obj, targetType, configuration);
}
+ @Override
+ public T remove(String path, Class returnType, Predicate... filters) {
+ notEmpty(path, "path can not be null or empty");
+ return remove(JsonPath.compile(path, filters), returnType);
+ }
+
+ public T remove(JsonPath path, Class returnType) {
+ notNull(path, "path can not be null");
+ return path.removeTyped(json, configuration, returnType);
+ }
private final class LimitingEvaluationListener implements EvaluationListener {
diff --git a/json-path/src/test/java/com/jayway/jsonpath/RemoveTest.java b/json-path/src/test/java/com/jayway/jsonpath/RemoveTest.java
new file mode 100644
index 00000000..cddd22f0
--- /dev/null
+++ b/json-path/src/test/java/com/jayway/jsonpath/RemoveTest.java
@@ -0,0 +1,59 @@
+package com.jayway.jsonpath;
+
+import static com.jayway.jsonpath.JsonPath.using;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Test;
+
+public class RemoveTest extends BaseTest {
+
+ @Test
+ public void fromJsonString() {
+ String result = JsonPath.remove("{\"val\":1,\"val2\":2}", "$.val");
+ assertThat(result).isEqualTo("{\"val2\":2}");
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void fromMap() {
+ Map model = new HashMap(){{
+ put("a", "a-val");
+ put("b", "b-val");
+ put("c", "c-val");
+ }};
+
+ Configuration conf = Configuration.defaultConfiguration();
+
+ assertThat(using(conf).parse(model).remove("$.b", Map.class))
+ .containsEntry("a", "a-val")
+ .containsEntry("c", "c-val").doesNotContainKey("b");
+ }
+
+ @Test
+ public void fromMapToString() {
+ Map model = new HashMap(){{
+ put("a", "a-val");
+ put("b", "b-val");
+ put("c", "c-val");
+ }};
+
+ Configuration conf = Configuration.defaultConfiguration();
+
+ assertThat(using(conf).parse(model).remove("$.b", String.class))
+ .contains("\"a\":\"a-val\"")
+ .contains("\"c\":\"c-val\"")
+ .doesNotContain("\"b\":\"b-val\"");
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void fromStringToMap() {
+ Configuration conf = Configuration.defaultConfiguration();
+
+ assertThat(using(conf).parse("{\"val\":1,\"val2\":2}").remove("$.val2", Map.class))
+ .containsEntry("val", 1).doesNotContainKey("val2");
+ }
+}
\ No newline at end of file