如何将以下from_str宏更改为from_json?

Har*_*aka 3 rust rust-macros

我有以下宏.请注意,这StringContent是一个枚举项.

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

这让我可以编写代码

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

现在,我想另一个宏from_json!,让我做摆脱了r#""#像这样

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

我尝试了以下似乎不起作用

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

我怎么from_json去上班?

Jan*_*ner 5

您的宏不起作用,因为concat!不能用于以语法合理的方式将标识符附加到彼此.它改为将标识符连接成一个字符串.你现在看起来像是"r#\" ~your JSON~ \"#",并且在r#其中#是文字字符.

在实施稳定的扩展之后,concat_idents!您的方法将无法工作.

您必须在宏中手动解析JSON语法.如需灵感,请了解Serde是如何做到的.

serde_json一般似乎很适合你的用例.如果可能的话,我建议删除任何JSON解析的自定义实现,而不是使用serde_json,因为它是Rust中所有JSON事实的标准选择.

这是如何使用serde_json将JSON转换为原始字符串的最小示例:

#[macro_use]
extern crate serde_json;

fn main() {
    let as_json_value = json!({
        "appName": "Demo App",
        "appVersion": "1.0",
        "database": {
            "host": "dev.database.com",
            "port": 3000
        }
    });
    let as_string = format!("{}", as_json_value);
    println!("{}", as_string);
}
Run Code Online (Sandbox Code Playgroud)

虽然你可能想要重写你的StringContent枚举serde_json::Value,因为它已经为你整齐地解析了.