diff --git a/Cargo.lock b/Cargo.lock
index f08a89f..402190b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -10,8 +10,11 @@ dependencies = [
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "mime 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 0.9.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "yup-hyper-mock 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -67,6 +70,11 @@ dependencies = [
 ]
 
 [[package]]
+name = "dtoa"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
 name = "env_logger"
 version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -152,6 +160,11 @@ dependencies = [
 ]
 
 [[package]]
+name = "itoa"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
 name = "kernel32-sys"
 version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -239,6 +252,11 @@ dependencies = [
 ]
 
 [[package]]
+name = "num-traits"
+version = "0.1.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
 name = "num_cpus"
 version = "1.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -281,6 +299,11 @@ version = "0.3.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
+name = "quote"
+version = "0.3.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
 name = "rand"
 version = "0.3.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -329,11 +352,63 @@ version = "0.1.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
+name = "serde"
+version = "0.9.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "serde_codegen_internals"
+version = "0.14.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "syn 0.11.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "serde_derive"
+version = "0.9.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "quote 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_codegen_internals 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.11.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "serde_json"
+version = "0.9.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "strsim"
 version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
+name = "syn"
+version = "0.11.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "quote 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "synom 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "synom"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "tempdir"
 version = "0.3.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -372,10 +447,10 @@ dependencies = [
 
 [[package]]
 name = "toml"
-version = "0.2.1"
+version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -410,6 +485,11 @@ version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
+name = "unicode-xid"
+version = "0.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
 name = "unreachable"
 version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -471,6 +551,7 @@ dependencies = [
 "checksum cmake 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "e1acc68a3f714627af38f9f5d09706a28584ba60dfe2cca68f40bf779f941b25"
 "checksum curl-sys 0.3.10 (registry+https://github.com/rust-lang/crates.io-index)" = "c0d909dc402ae80b6f7b0118c039203436061b9d9a3ca5d2c2546d93e0a61aaa"
 "checksum docopt 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab32ea6e284d87987066f21a9e809a73c14720571ef34516f0890b3d355ccfd8"
+"checksum dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80c8b71fd71146990a9742fc06dcbbde19161a267e0ad4e572c35162f4578c90"
 "checksum env_logger 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ed39959122ea027670b704fb70539f4286ddf4a49eefede23bf0b4b2a069ec03"
 "checksum foreign-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e4056b9bd47f8ac5ba12be771f77a0dae796d1bbaaf5fd0b9c2d38b69b8a29d"
 "checksum gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)" = "c07c758b972368e703a562686adb39125707cc1ef3399da8c019fc6c2498a75d"
@@ -480,6 +561,7 @@ dependencies = [
 "checksum hyper 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)" = "220407e5a263f110ec30a071787c9535918fdfc97def5680c90013c3f30c38c1"
 "checksum hyper-openssl 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "724e697539067177f7edcd31fccf5eeebff95f1603b72f1d304d0dc1fe1570b0"
 "checksum idna 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1053236e00ce4f668aeca4a769a09b3bf5a682d802abd6f3cb39374f6b162c11"
+"checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c"
 "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
 "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a"
 "checksum lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6abe0ee2e758cd6bc8a2cd56726359007748fbf4128da998b65d0b70f881e19b"
@@ -491,11 +573,13 @@ dependencies = [
 "checksum matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "efd7622e3022e1a6eaa602c4cea8912254e5582c9c692e9167714182244801b1"
 "checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4"
 "checksum mime 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b5c93a4bd787ddc6e7833c519b73a50883deb5863d76d9b71eb8216fb7f94e66"
+"checksum num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "e1cbfa3781f3fe73dc05321bed52a06d2d491eaa764c52335cf4399f046ece99"
 "checksum num_cpus 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a18c392466409c50b87369414a2680c93e739aedeb498eb2bff7d7eb569744e2"
 "checksum openssl 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f9871ecf7629da3760599e3e547d35940cff3cead49159b49f81cd1250f24f1d"
 "checksum openssl-probe 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "756d49c8424483a3df3b5d735112b4da22109ced9a8294f1f5cdf80fb3810919"
 "checksum openssl-sys 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)" = "5dd48381e9e8a6dce9c4c402db143b2e243f5f872354532f7a009c289b3998ca"
 "checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903"
+"checksum quote 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "7375cf7ad34a92e8fd18dd9c42f58b9a11def59ab48bec955bf359a788335592"
 "checksum rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "022e0636ec2519ddae48154b028864bdce4eaf7d35226ab8e65c611be97b189d"
 "checksum redox_syscall 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "8dd35cc9a8bdec562c757e3d43c1526b5c6d2653e23e2315065bc25556550753"
 "checksum regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4278c17d0f6d62dfef0ab00028feb45bd7d2102843f80763474eeb1be8a10c01"
@@ -503,17 +587,24 @@ dependencies = [
 "checksum rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "237546c689f20bb44980270c73c3b9edd0891c1be49cc1274406134a66d3957b"
 "checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084"
 "checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac"
+"checksum serde 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)" = "a78def33a828eb05eb7f0167499f19cca368faf27601f6c43bc70316825d9adf"
+"checksum serde_codegen_internals 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4d52006899f910528a10631e5b727973fe668f3228109d1707ccf5bad5490b6e"
+"checksum serde_derive 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)" = "789ee9f3cd78c850948b94121020147f5220b47dafbf230d7098a93a58f726cf"
+"checksum serde_json 0.9.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6501ac6f8b74f9b1033f7ddf79a08edfa0f58d6f8e3190cb8dc97736afa257a8"
 "checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
+"checksum syn 0.11.8 (registry+https://github.com/rust-lang/crates.io-index)" = "37c279fb816210c9bb28b2c292664581e7b87b4561e86b94df462664d8620bb8"
+"checksum synom 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "27e31aa4b09b9f4cb12dff3c30ba503e17b1a624413d764d32dab76e3920e5bc"
 "checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6"
 "checksum thread-id 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4437c97558c70d129e40629a5b385b3fb1ffac301e63941335e4d354081ec14a"
 "checksum thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c85048c6260d17cf486ceae3282d9fb6b90be220bf5b28c400f5485ffc29f0c7"
 "checksum time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "211b63c112206356ef1ff9b19355f43740fc3f85960c598a93d3a3d3ba7beade"
-"checksum toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "736b60249cb25337bc196faa43ee12c705e426f3d55c214d73a4e7be06f92cb4"
+"checksum toml 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3474f3c6eaf32eedb4f4a66a26214f020f828a6d96c37e38a35e3a379bbcfd11"
 "checksum traitobject 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "07eaeb7689bb7fca7ce15628319635758eda769fed481ecfe6686ddef2600616"
 "checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887"
 "checksum unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "13a5906ca2b98c799f4b1ab4557b76367ebd6ae5ef14930ec841c74aed5f3764"
 "checksum unicode-bidi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d3a078ebdd62c0e71a709c3d53d2af693fe09fe93fbff8344aebe289b78f9032"
 "checksum unicode-normalization 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e28fa37426fceeb5cf8f41ee273faa7c82c47dc8fba5853402841e665fcd86ff"
+"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
 "checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91"
 "checksum url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5ba8a749fb4479b043733416c244fa9d1d3af3d7c23804944651c8a448cb87e"
 "checksum user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ef4711d107b21b410a3a974b1204d9accc8b10dad75d8324b5d755de1617d47"
diff --git a/Cargo.toml b/Cargo.toml
index b363292..9153ff2 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -37,8 +37,11 @@ hyper-openssl = "0.2"
 git2 = "0.6"
 rustc-serialize = "0.3"
 url = "1.4"
+serde = "0.9"
+serde_derive = "0.9"
+serde_json = "0.9"
 mime = "0.2"
-toml = "0.2"
+toml = "0.3"
 tempdir = "0.3"
 docopt = "0.7"
 log = "0.3"
diff --git a/src/jenkins.rs b/src/jenkins.rs
index d2faad7..85a098b 100644
--- a/src/jenkins.rs
+++ b/src/jenkins.rs
@@ -22,7 +22,6 @@
 
 extern crate hyper;
 extern crate url;
-extern crate rustc_serialize;
 
 use std::io::Read;
 use std::time::Duration;
@@ -33,7 +32,7 @@ use std::collections::BTreeMap;
 use hyper::Client;
 use hyper::client::{IntoUrl, RequestBuilder};
 use hyper::header::{Headers, Basic, Authorization, Location};
-use rustc_serialize::json::Json;
+use serde_json::{self, Value};
 
 use patchwork::TestState;
 
@@ -106,15 +105,16 @@ impl JenkinsBackend {
         self.hyper_client.post(url).headers(self.headers())
     }
 
-    fn get_api_json_object(&self, base_url: &str) -> rustc_serialize::json::Object {
+    fn get_api_json_object(&self, base_url: &str) -> Value {
         // TODO: Don't panic on failure, fail more gracefully
         let url = format!("{}api/json", base_url);
         let mut resp = self.get(&url).send().expect("HTTP request error");
         let mut result_str = String::new();
         resp.read_to_string(&mut result_str)
             .unwrap_or_else(|err| panic!("Couldn't read from server: {}", err));
-        let json = Json::from_str(&result_str).unwrap_or_else(|err| panic!("Couldn't parse JSON from Jenkins: {}", err));
-        json.as_object().unwrap().clone()
+        serde_json::from_str(&result_str).unwrap_or_else(
+            |err| panic!("Couldn't parse JSON from Jenkins: {}", err)
+        )
     }
 
     pub fn get_build_url(&self, build_queue_entry: &str) -> Option<String> {
@@ -124,9 +124,9 @@ impl JenkinsBackend {
                 Some(exec) => return Some(exec
                                           .as_object() // Option<BTreeMap>
                                           .unwrap() // BTreeMap
-                                          .get("url") // Option<&str> ?
+                                          .get("url") // Option<&str>
                                           .unwrap() // &str ?
-                                          .as_string()
+                                          .as_str()
                                           .unwrap()
                                           .to_string()),
                 None => sleep(Duration::from_millis(JENKINS_POLLING_INTERVAL)),
@@ -135,7 +135,7 @@ impl JenkinsBackend {
     }
 
     pub fn get_build_status(&self, build_url: &str) -> JenkinsBuildStatus {
-        if self.get_api_json_object(build_url)["building"].as_boolean().unwrap() {
+        if self.get_api_json_object(build_url)["building"].as_bool().unwrap() {
             JenkinsBuildStatus::Running
         } else {
             JenkinsBuildStatus::Done
@@ -144,13 +144,13 @@ impl JenkinsBackend {
 
     pub fn get_build_result(&self, build_url: &str) -> Option<TestState> {
         match self.get_api_json_object(build_url).get("result").unwrap()
-            .as_string() {
+            .as_str() {
             None => None,
             Some(result) => match result { // TODO: Improve this...
-                "SUCCESS" => Some(TestState::success),
-                "FAILURE" => Some(TestState::failure),
-                "UNSTABLE" => Some(TestState::warning),
-                _ => Some(TestState::pending),
+                "SUCCESS" => Some(TestState::Success),
+                "FAILURE" => Some(TestState::Fail),
+                "UNSTABLE" => Some(TestState::Warning),
+                _ => Some(TestState::Pending),
             },
         }
     }
diff --git a/src/main.rs b/src/main.rs
index d27ddd6..7941a90 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -23,13 +23,17 @@ extern crate hyper;
 extern crate hyper_openssl;
 extern crate rustc_serialize;
 extern crate git2;
-extern crate toml;
 extern crate tempdir;
 extern crate docopt;
 extern crate url;
 #[macro_use]
 extern crate log;
 extern crate env_logger;
+extern crate serde;
+#[macro_use]
+extern crate serde_derive;
+extern crate serde_json;
+extern crate toml;
 
 use git2::{BranchType, RemoteCallbacks, PushOptions};
 
@@ -200,7 +204,7 @@ fn test_patch(settings: &Config, client: &Arc<Client>, project: &Project, path:
                 successfully_applied = true;
                 results.push(TestResult {
                     test_name: "apply_patch".to_string(),
-                    state: TestState::success,
+                    state: TestState::Success,
                     url: None,
                     summary: Some(format!("Successfully applied to branch {}", branch_name)),
                 });
@@ -209,7 +213,7 @@ fn test_patch(settings: &Config, client: &Arc<Client>, project: &Project, path:
                 // It didn't apply.  No need to bother testing.
                 results.push(TestResult {
                     test_name: "apply_patch".to_string(),
-                    state: TestState::warning,
+                    state: TestState::Warning,
                     url: None,
                     summary: Some(format!("Failed to apply to branch {}", branch_name)),
                 });
@@ -235,7 +239,7 @@ fn test_patch(settings: &Config, client: &Arc<Client>, project: &Project, path:
     if !successfully_applied {
         results.push(TestResult {
             test_name: "apply_patch".to_string(),
-            state: TestState::failure,
+            state: TestState::Fail,
             url: None,
             summary: Some("Failed to apply to any branch".to_string()),
         });
@@ -260,7 +264,7 @@ fn main() {
         .and_then(|d| d.version(Some(version)).decode())
         .unwrap_or_else(|e| e.exit());
 
-    let settings = settings::parse(args.arg_config_file);
+    let settings = settings::parse(&args.arg_config_file);
 
     // The HTTP client we'll use to access the APIs
     // TODO: HTTPS support, not yet implemented in Hyper as of 0.9.6
diff --git a/src/patchwork.rs b/src/patchwork.rs
index b9308c3..cf41a52 100644
--- a/src/patchwork.rs
+++ b/src/patchwork.rs
@@ -31,7 +31,7 @@ use hyper::mime::{Mime, TopLevel, SubLevel, Attr, Value};
 use hyper::status::StatusCode;
 use hyper::client::response::Response;
 
-use rustc_serialize::json::{self, DecoderError};
+use serde_json;
 
 use utils;
 
@@ -41,7 +41,7 @@ pub static PATCHWORK_QUERY: &'static str = "?ordering=-last_updated&related=expa
 
 // /api/1.0/projects/*/series/
 
-#[derive(RustcDecodable, Clone)]
+#[derive(Deserialize, Clone)]
 pub struct Project {
     pub id: u64,
     pub name: String,
@@ -52,13 +52,13 @@ pub struct Project {
     pub webscm_url: Option<String>
 }
 
-#[derive(RustcDecodable, Clone)]
+#[derive(Deserialize, Clone)]
 pub struct Submitter {
     pub id: u64,
     pub name: String
 }
 
-#[derive(RustcDecodable, Clone)]
+#[derive(Deserialize, Clone)]
 pub struct Series {
     pub id: u64,
     pub project: Project,
@@ -72,7 +72,7 @@ pub struct Series {
     pub test_state: Option<String>
 }
 
-#[derive(RustcDecodable)]
+#[derive(Deserialize)]
 pub struct SeriesList {
     pub count: u64,
     pub next: Option<String>,
@@ -80,24 +80,26 @@ pub struct SeriesList {
     pub results: Option<Vec<Series>>
 }
 
-// TODO: remove this when we have Jenkins result handling
-#[allow(warnings)] // for not being camelcase because encoding
-#[derive(RustcEncodable, Clone)]
+#[derive(Serialize, Clone)]
 pub enum TestState {
-    pending,
-    success,
-    warning,
-    failure,
+    #[serde(rename = "pending")]
+    Pending,
+    #[serde(rename = "success")]
+    Success,
+    #[serde(rename = "warning")]
+    Warning,
+    #[serde(rename = "fail")]
+    Fail,
 }
 
 impl Default for TestState {
     fn default() -> TestState {
-        TestState::pending
+        TestState::Pending
     }
 }
 
 // /api/1.0/series/*/revisions/*/test-results/
-#[derive(RustcEncodable)]
+#[derive(Serialize)]
 pub struct TestResult {
     pub test_name: String,
     pub state: TestState,
@@ -149,7 +151,7 @@ impl PatchworkServer {
     pub fn post_test_result(&self, result: TestResult,
                             series_id: &u64, series_revision: &u64)
                             -> Result<StatusCode, hyper::error::Error> {
-        let encoded = json::encode(&result).unwrap();
+        let encoded = serde_json::to_string(&result).unwrap();
         let headers = self.headers.clone();
         debug!("JSON Encoded: {}", encoded);
         let res = try!(self.client.post(&format!(
@@ -160,10 +162,10 @@ impl PatchworkServer {
         Ok(res.status)
     }
 
-    pub fn get_series(&self, series_id: &u64) -> Result<Series, DecoderError> {
+    pub fn get_series(&self, series_id: &u64) -> Result<Series, serde_json::Error> {
         let url = format!("{}{}/series/{}{}", &self.url, PATCHWORK_API,
                           series_id, PATCHWORK_QUERY);
-        json::decode(&self.get(&url).unwrap())
+        serde_json::from_str(&self.get(&url).unwrap())
     }
 
     pub fn get_series_mbox(&self, series_id: &u64, series_revision: &u64)
@@ -174,10 +176,10 @@ impl PatchworkServer {
             .header(Connection::close()).send()
     }
 
-    pub fn get_series_query(&self) -> Result<SeriesList, DecoderError> {
+    pub fn get_series_query(&self) -> Result<SeriesList, serde_json::Error> {
         let url = format!("{}{}/series/{}", &self.url,
                           PATCHWORK_API, PATCHWORK_QUERY);
-        json::decode(&self.get(&url).unwrap_or_else(
+        serde_json::from_str(&self.get(&url).unwrap_or_else(
             |err| panic!("Failed to connect to Patchwork: {}", err)))
     }
 
diff --git a/src/settings.rs b/src/settings.rs
index b2cd4d6..e05bc98 100644
--- a/src/settings.rs
+++ b/src/settings.rs
@@ -15,19 +15,16 @@
 //
 
 use toml;
-use toml::{Parser, Value};
 
 use git2::{Repository, Error};
 
-use rustc_serialize::Decodable;
-
 use std::fs::File;
 use std::io::Read;
 use std::collections::BTreeMap;
 
 // TODO: Give more informative error messages when we fail to parse.
 
-#[derive(RustcDecodable, Clone)]
+#[derive(Deserialize, Clone)]
 pub struct Git {
     pub user: String,
     pub public_key: Option<String>,
@@ -35,7 +32,7 @@ pub struct Git {
     pub passphrase: Option<String>
 }
 
-#[derive(RustcDecodable, Clone)]
+#[derive(Deserialize, Clone)]
 pub struct Patchwork {
     pub url: String,
     pub port: Option<u16>,
@@ -45,7 +42,7 @@ pub struct Patchwork {
 }
 
 // TODO: make this CI server agnostic (i.e buildbot or whatever)
-#[derive(RustcDecodable, Clone)]
+#[derive(Deserialize, Clone)]
 pub struct Jenkins {
     pub url: String,
     pub port: Option<u16>,
@@ -54,7 +51,7 @@ pub struct Jenkins {
     pub token: Option<String>
 }
 
-#[derive(RustcDecodable, Clone)]
+#[derive(Deserialize, Clone)]
 pub struct Project {
     pub repository: String,
     pub branches: Vec<String>,
@@ -71,7 +68,7 @@ impl Project {
     }
 }
 
-#[derive(RustcDecodable, Clone)]
+#[derive(Deserialize, Clone)]
 pub struct Config {
     pub git: Git,
     pub patchwork: Patchwork,
@@ -86,7 +83,7 @@ pub fn get_job_title(job: &BTreeMap<String, String>) -> String {
     }
 }
 
-pub fn parse(path: String) -> Config {
+pub fn parse(path: &str) -> Config {
     let mut toml_config = String::new();
 
     let mut file = match File::open(&path) {
@@ -97,23 +94,13 @@ pub fn parse(path: String) -> Config {
     file.read_to_string(&mut toml_config)
         .unwrap_or_else(|err| panic!("Couldn't read config: {}", err));
 
-    let mut parser = Parser::new(&toml_config);
-    let toml = parser.parse();
+    let toml_config = toml::de::from_str::<Config>(&toml_config);
 
-    if toml.is_none() {
-        for err in &parser.errors {
-            let (loline, locol) = parser.to_linecol(err.lo);
-            let (hiline, hicol) = parser.to_linecol(err.hi);
-            error!("TOML parsing error: {} in {} at {}:{}-{}:{}",
-                    err.desc, path, loline, locol, hiline, hicol);
+    match toml_config {
+        Ok(config_inside) => config_inside,
+        Err(err) => {
+            error!("TOML error: {}", err);
+            panic!("Could not parse configuration file, exiting");
         }
-        panic!("Syntax error in TOML file, exiting.");
-    }
-
-    let config = Value::Table(toml.unwrap());
-
-    match Config::decode::<toml::Decoder>(&mut toml::Decoder::new(config)) {
-        Ok(t) => t,
-        Err(err) => panic!(format!("Couldn't deserialise config: {:?}", err))
     }
 }
