Search code examples
rustrust-macros

How do I change the following from_str macro to from_json?


I have the following macro. Note that StringContent is an enum item.

#[macro_export]
macro_rules! from_str {  
    ($json:expr) => {         
        StringContent(String::from($json))
    }
}

which allows me to write code like

from_str!(r#"{
    "appName": "Demo App",
    "appVersion": "1.0",
    "database": {
        "host": "dev.database.com",
        "port": 3000
    }
}"#)

Now I want another macro from_json! which allows me to do get rid of the r#""# like so

from_json!({
    "appName": "Demo App",
    "appVersion": "1.0",
    "database": {
        "host": "dev.database.com",
        "port": 3000
    }
})

I've tried the following which does not seem to work

#[macro_export]
macro_rules! from_json {  
    ($t:tt) => {         
        StringContent(String::from(concat!(r#"r#""#, stringify!($t), r#"""# , r#"#"#)))
    }
}

How can I get from_json to work?


Solution

  • I'd just use the json macro provided by serde_json, which works with your exact syntax:

    #[macro_use]
    extern crate serde_json;
    extern crate serde;
    
    fn main() {
        let x = json!({
            "appName": "Demo App",
            "appVersion": "1.0",
            "database": {
                "host": "dev.database.com",
                "port": 3000
            }
        });
    }
    

    This creates a Value struct. If for some reason you really needed it back as a string, you'd need to re-serialize it using it's Display implementation:

    extern crate serde;
    #[macro_use]
    extern crate serde_json;
    
    struct StringContent(String);
    
    macro_rules! from_json {
        ($x:tt) => {{
            StringContent(json!($x).to_string())
        }}
    }
    
    fn main() {
        let x = from_json!({
                "appName": "Demo App",
                "appVersion": "1.0",
                "database": {
                    "host": "dev.database.com",
                    "port": 3000
                }
            });
    
        println!("{}", x.0)
    }