diff --git a/src/ptr.rs b/src/ptr.rs
index 57dacf6ed0ecd0f2577e28b0aae5302c2b220e6c..8525da0298fde69e5027c02757d24a8a48489178 100644
--- a/src/ptr.rs
+++ b/src/ptr.rs
@@ -96,6 +96,18 @@ impl<S: AsRef<str>, C: AsRef<[S]>> JsonPointer<S, C> {
     }
 }
 
+impl<S: AsRef<str>> JsonPointer<S, Vec<S>> {
+    /// Adds a component to the JSON pointer.
+    pub fn push(&mut self, component: S) {
+        self.ref_toks.push(component);
+    }
+
+    /// Removes and returns the last component from the JSON pointer.
+    pub fn pop(&mut self) -> Option<S> {
+        self.ref_toks.pop()
+    }
+}
+
 impl<S: AsRef<str>, C: AsRef<[S]>> Display for JsonPointer<S, C> {
     fn fmt(&self, fmt: &mut Formatter) -> FmtResult {
         for part in self.ref_toks.as_ref().iter() {
diff --git a/tests/push_pop.rs b/tests/push_pop.rs
new file mode 100644
index 0000000000000000000000000000000000000000..3334212ba66dd6a45e1cdf554630b1b550572840
--- /dev/null
+++ b/tests/push_pop.rs
@@ -0,0 +1,29 @@
+extern crate json_pointer;
+#[macro_use]
+extern crate quickcheck;
+
+use json_pointer::JsonPointer;
+use quickcheck::TestResult;
+
+quickcheck! {
+
+/// Pushing then popping should not affect the pointer or the pushed/popped
+/// value.
+fn push_then_pop_is_identity(s: String, t: String) -> TestResult {
+    match s.parse::<JsonPointer<_, _>>() {
+        Ok(mut ptr) => {
+            let str1 = ptr.to_string();
+            ptr.push(t.clone());
+            let t2 = ptr.pop();
+            let str2 = ptr.to_string();
+            if Some(t) == t2 && str1 == str2 {
+                TestResult::passed()
+            } else {
+                TestResult::failed()
+            }
+        },
+        Err(_) => TestResult::discard(),
+    }
+}
+
+}