Skip to content

Conditional compilation ignores serde_as(as = X) #355

@philher

Description

@philher

Using conditional compilation appears to break the use of serde_as. Using a struct such as StructC below, I would expect it to be serialized to JSON without issue, as happens without using non conditional compilation.
However, the attribute appears to have no effect, instead failing with the error Error("key must be a string", line: 0, column: 0).

Is this really a bug, or is there something I am not doing right ? I have also given a full example with tests that showcase the problem and what works.

#[cfg_attr(feature="serde_test" ,serde_as)]
#[derive(Default, Debug, Serialize, Deserialize)]
struct StructC {
    #[cfg_attr(feature="serde_test" ,serde_as(as = "Vec<(_, _)>"))]
    map :  HashMap<(i32,i32), i32>
}
lib.rs
use serde::{Deserialize, Serialize};
use serde_with::serde_as;
use std::collections::HashMap;

/// Works
#[serde_as]
#[derive(Default, Debug, Serialize, Deserialize)]
struct StructA {
    #[serde_as(as = "Vec<(_, _)>")]
    map: HashMap<(i32, i32), i32>,
}

/// Fails as expected
#[derive(Default, Debug, Serialize, Deserialize)]
struct StructB {
    map: HashMap<(i32, i32), i32>,
}

/// Should work
#[cfg_attr(feature = "serde_test", serde_as)]
#[derive(Default, Debug, Serialize, Deserialize)]
struct StructC {
    #[cfg_attr(feature = "serde_test", serde_as(as = "Vec<(_, _)>"))]
    map: HashMap<(i32, i32), i32>,
}

/// Should work or not ?
#[serde_as]
#[derive(Default, Debug, Serialize, Deserialize)]
struct StructD {
    #[cfg_attr(feature = "serde_test", serde_as(as = "Vec<(_, _)>"))]
    map: HashMap<(i32, i32), i32>,
}

/// Shows that other attributes work
#[derive(Default, Debug, Serialize, Deserialize)]
struct StructE {
    #[cfg_attr(feature = "serde_test", serde(rename = "renamed"))]
    map: HashMap<String, i32>,
}

#[cfg(test)]
mod tests {
    use crate::{StructA, StructB, StructC, StructD, StructE};

    #[test]
    fn test_struct_a() {
        assert!(cfg!(feature = "serde_test"));
        let mut struct_a = StructA::default();
        struct_a.map.insert((1, -10), -1);

        let a_str = serde_json::to_string(&struct_a);
        println!("{:?}", a_str);
        assert_eq!(a_str.unwrap(), r#"{"map":[[[1,-10],-1]]}"#.to_string());
    }

    #[test]
    fn test_struct_b() {
        assert!(cfg!(feature = "serde_test"));
        let mut struct_b = StructB::default();
        struct_b.map.insert((1, -10), -1);

        let b_str = serde_json::to_string(&struct_b);
        println!("{:?}", b_str);
        assert!(b_str.is_err());
    }

    #[test]
    fn test_struct_c() {
        assert!(cfg!(feature = "serde_test"));
        let mut struct_c = StructC::default();
        struct_c.map.insert((1, -10), -1);

        let c_str = serde_json::to_string(&struct_c);
        println!("{:?}", c_str);
        assert_eq!(c_str.unwrap(), r#"{"map":[[[1,-10],-1]]}"#.to_string());
    }
    #[test]
    fn test_struct_d() {
        assert!(cfg!(feature = "serde_test"));
        let mut struct_d = StructD::default();
        struct_d.map.insert((1, -10), -1);

        let d_str = serde_json::to_string(&struct_d);
        println!("{:?}", d_str);
        assert_eq!(d_str.unwrap(), r#"{"map":[[[1,-10],-1]]}"#.to_string());
    }
    #[test]
    fn test_struct_e() {
        assert!(cfg!(feature = "serde_test"));
        let mut struct_e = StructE::default();
        struct_e.map.insert("a_key".to_string(), -1);

        let e_str = serde_json::to_string(&struct_e);
        println!("{:?}", e_str);
        assert_eq!(e_str.unwrap(), r#"{"renamed":{"a_key":-1}}"#.to_string());
    }
}
cargo.toml
[package]
name = "mwe_issue"
version = "0.1.0"
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
serde = "1.0.130"
serde_with = "1.9.4"
serde_json = "1.0.67"


[features]
serde_test = []

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingdocumentationImprovements or additions to documentationwontfixThis will not be worked on

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions