title: Deserializing an optional struct field with a generic type leads to semantic weirdness
body: <p>I am attempting to deserialize JSON into a struct that contains an optional field <code>authorization</code>. The JSON may or may not include this field. If it does include the field, I'm doing a custom deserialization into a <code>hyper::header::Authorization&lt;hyper::header::Scheme&gt;</code>. Because <code>Authorization</code> requires a generic type for <code>Scheme</code>, I'm required (as I've written it) to include the generic type on my struct.</p>
  
  <p>All of the tests pass, but the last one (<code>de_json_none</code>, the one for JSON <em>without</em> the authorization field) is semantically weird because I have to target a variable with a definite <code>Scheme</code> type (either <code>Bearer</code> as shown or <code>Basic</code>), neither of which makes any sense for that data, despite being perfectly valid from Rust's perspective.</p>
  
  <p>It's clear why that is the case, but it's something I don't want and something I'm not sure how to fix. </p>
  
  <p>I want to write a Rocket handler that only matches data that contains the authorization field of type <code>Authorization&lt;Bearer&gt;</code> by setting the data type to <code>Headers&lt;Bearer&gt;</code>. At the moment, it would also match data that doesn't have the field at all. I'm also stuck without a clear way to call out the data with the missing field specifically by type.</p>
  
  <p>I'm looking for suggestions on how to refactor this code to reflect the fact that <code>Headers</code> really has three distinct, mutually-exclusive incarnations (<code>Basic</code>, <code>Bearer</code> and <code>None</code>). Perhaps I should be looking to do something with an enum here?</p>
  
  <pre><code>extern crate hyper;
  extern crate serde;
  extern crate serde_json;
  #[macro_use]
  extern crate serde_derive;
  
  use hyper::header::{Authorization, Header, Raw, Scheme};
  use serde::{Deserialize, Deserializer};
  
  #[derive(Debug, Deserialize, PartialEq)]
  struct Headers&lt;S&gt;
  where
      S: Scheme + 'static,
  {
      #[serde(deserialize_with = "auth_header", default = "no_auth")]
      authorization: Option&lt;Authorization&lt;S&gt;&gt;,
      #[serde(rename = ":path")]
      path: String,
  }
  
  fn auth_header&lt;'de, D, S&gt;(deserializer: D) -&gt; Result&lt;Option&lt;Authorization&lt;S&gt;&gt;, D::Error&gt;
  where
      D: Deserializer&lt;'de&gt;,
      S: Scheme + 'static,
  {
      let s = String::deserialize(deserializer)?;
      let auth = Authorization::parse_header(&amp;Raw::from(s.into_bytes()));
      auth.map(|a| Some(a)).map_err(serde::de::Error::custom)
  }
  
  fn no_auth&lt;S&gt;() -&gt; Option&lt;Authorization&lt;S&gt;&gt;
  where
      S: Scheme + 'static,
  {
      None
  }
  
  #[cfg(test)]
  mod test {
      use hyper::header::{Basic, Bearer};
      use serde_json;
      use super::*;
  
      #[test]
      fn de_json_basic() {
          let data = r#"{
                          "authorization": "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==",
                          ":path": "/service/",
                          ":method": "GET"
                        }"#;
  
          let message = Headers {
              authorization: Some(Authorization(Basic {
                  username: "Aladdin".to_owned(),
                  password: Some("open sesame".to_owned()),
              })),
              path: "/service/".to_owned(),
          };
  
          let h: Headers&lt;Basic&gt; = serde_json::from_str(data).unwrap();
  
          assert_eq!(message, h);
      }
  
      #[test]
      fn de_json_bearer() {
          let data = r#"{
                          "authorization": "Bearer fpKL54jvWmEGVoRdCNjG",
                          ":path": "/service/",
                          ":method": "GET"
                        }"#;
  
          let message = Headers {
              authorization: Some(Authorization(
                  Bearer { token: "fpKL54jvWmEGVoRdCNjG".to_owned() },
              )),
              path: "/service/".to_owned(),
          };
  
          let h: Headers&lt;Bearer&gt; = serde_json::from_str(data).unwrap();
  
          assert_eq!(message, h);
      }
  
      #[test]
      fn de_json_none() {
          let data = r#"{
                          ":path": "/service/",
                          ":method": "GET"
                        }"#;
  
          let message = Headers {
              authorization: None,
              path: "/service/".to_owned(),
          };
  
          let h: Headers&lt;Bearer&gt; = serde_json::from_str(data).unwrap();
          // this also works, though neither should ideally
          // let h: Headers&lt;Basic&gt; = serde_json::from_str(data).unwrap();
  
          assert_eq!(message, h);
      }
  }
  </code></pre>