From 412ed9738998356d82750ba4001e17aba8cebc54 Mon Sep 17 00:00:00 2001 From: Warts Werdna Date: Sat, 19 Mar 2016 11:40:58 +0100 Subject: [PATCH] custom json encoder omits None when serializing --- src/lib.rs | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 451c391..6b2701e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,6 +10,7 @@ extern crate crypto; use rustc_serialize::{json, Encodable, Decodable}; use rustc_serialize::base64::{self, ToBase64, FromBase64}; +use rustc_serialize::json::{ToJson, Json}; use crypto::sha2::{Sha256, Sha384, Sha512}; use crypto::hmac::Hmac; use crypto::mac::Mac; @@ -18,6 +19,7 @@ use crypto::util::fixed_time_eq; pub mod errors; use errors::Error; +use std::collections::BTreeMap; #[derive(Debug, PartialEq, Copy, Clone, RustcDecodable, RustcEncodable)] /// The algorithms supported for signing/verifying @@ -27,6 +29,16 @@ pub enum Algorithm { HS512 } +impl ToJson for Algorithm { + fn to_json(&self) -> Json { + match self { + &Algorithm::HS256 => Json::String("HS256".to_owned()), + &Algorithm::HS384 => Json::String("HS384".to_owned()), + &Algorithm::HS512 => Json::String("HS512".to_owned()), + } + } +} + /// A part of the JWT: header and claims specifically /// Allows converting from/to struct with base64 pub trait Part { @@ -51,7 +63,7 @@ impl Part for T where T: Encodable + Decodable { } } -#[derive(Debug, PartialEq, RustcDecodable, RustcEncodable)] +#[derive(Debug, PartialEq, RustcDecodable)] /// A basic JWT header part, the alg defaults to HS256 and typ is automatically /// set to `JWT`. All the other fields are optional pub struct Header { @@ -82,6 +94,35 @@ impl Default for Header { } } +impl Encodable for Header { + fn encode(&self, s: &mut S) -> Result<(), S::Error> { + self.to_json().encode(s) + } +} + +impl ToJson for Header { + fn to_json(&self) -> Json { + let mut d = BTreeMap::new(); + d.insert("typ".to_string(), self.typ.to_json()); + d.insert("alg".to_string(), self.alg.to_json()); + + // Define a macro to reduce boilerplate. + macro_rules! optional { + ($field_name:ident) => ( + match self.$field_name { + Some(ref value) => { d.insert(stringify!($field_name).to_string(), value.to_json()); }, + None => {}, + } + ) + } + optional!(jku); + optional!(kid); + optional!(x5u); + optional!(x5t); + Json::Object(d) + } +} + #[derive(Debug)] /// The return type of a successful call to decode(...) pub struct TokenData {