title: Deserializing an enum using a combination of #[serde(untagged)] and #[serde(with)]
body: <p>I'm trying to use an actix-web server as a gateway to a small stack to guarantee a strict data format inside of the stack while allowing some freedoms for the user.</p>
  <p>To do that, I want to deserialize a JSON string to the struct, then validate it, serialize it again and publish it on a message broker. The main part of the data is an array of arrays that contain integers, floats and datetimes. I'm using serde for deserialization  and chrono to deal with datetimes.</p>
  <p>I tried using a struct combined with an enum to allow the different types:</p>
  <pre><code>#[derive(Serialize, Deserialize)]
  pub struct Data {
      pub column_names: Option&lt;Vec&lt;String&gt;&gt;,
      pub values: Vec&lt;Vec&lt;ValueType&gt;&gt;,
  }
  
  #[derive(Serialize, Deserialize)]
  #[serde(untagged)]
  pub enum ValueType {
      I32(i32),
      F64(f64),
      #[serde(with = &quot;datetime_handler&quot;)]
      Dt(DateTime&lt;Utc&gt;),
  }
  </code></pre>
  <p>Since <code>chrono::DateTime&lt;T&gt;</code> does not implement <code>Serialize</code>, I added a custom module for that similar to how it is described <a href="https://serde.rs/custom-date-format.html" rel="nofollow noreferrer">in the serde docs</a>.</p>
  <pre><code>mod datetime_handler {
      use chrono::{DateTime, TimeZone, Utc};
      use serde::{self, Deserialize, Deserializer, Serializer};
  
      pub fn serialize&lt;S&gt;(dt: &amp;DateTime&lt;Utc&gt;, serializer: S) -&gt; Result&lt;S::Ok, S::Error&gt;
      where
          S: Serializer,
      {
          let s = dt.to_rfc3339();
          serializer.serialize_str(&amp;s)
      }
  
      pub fn deserialize&lt;'de, D&gt;(deserializer: D) -&gt; Result&lt;DateTime&lt;Utc&gt;, D::Error&gt;
      where
          D: Deserializer&lt;'de&gt;,
      {
          println!(&quot;Checkpoint 1&quot;);
          let s = String::deserialize(deserializer)?;
          println!(&quot;{}&quot;, s);
          println!(&quot;Checkpoint 2&quot;);
          let err1 = match DateTime::parse_from_rfc3339(&amp;s) {
              Ok(dt) =&gt; return Ok(dt.with_timezone(&amp;Utc)),
              Err(e) =&gt; Err(e),
          };
          println!(&quot;Checkpoint 3&quot;);
  
          const FORMAT1: &amp;'static str = &quot;%Y-%m-%d %H:%M:%S&quot;;
          match Utc.datetime_from_str(&amp;s, FORMAT1) {
              Ok(dt) =&gt; return Ok(dt.with_timezone(&amp;Utc)),
              Err(e) =&gt; println!(&quot;{}&quot;, e), // return first error not second if both fail
          };
          println!(&quot;Checkpoint 4&quot;);
          
          return err1.map_err(serde::de::Error::custom);
      }
  }
  </code></pre>
  <p>This tries 2 different time formats one after the other and works for DateTime strings.</p>
  <h3>The Problem</h3>
  It seems like the combination of `#[derive(Serialize, Deserialize)]`, `#[serde(untagged)]` and `#[serde(with)]` does something unexpected. `serde:from_str(...)` tries to deserialize every entry in the array with my custom `deserialize` function.
  I would expect it to either try to deserialize into `ValueType::I32` first, succeed and continue with the next entry, as [the docs](https://serde.rs/enum-representations.html) say:
  <blockquote>
  <p>Serde will try to match the data against each variant in order and the first one that deserializes successfully is the one returned.</p>
  </blockquote>
  <p>What happens is that the custom <code>deserialize</code>is applied to e.g. <code>&quot;0&quot;</code> fails and the deserialization stops.</p>
  <p>What's going on? How do I solve it?</p>
  <p>My ideas are that I either fail to deserialize in the wrong way or that I somehow &quot;overwrite&quot; the derived deserialize with my own.</p>