3

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

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

这使我可以编写类似的代码

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

现在我想要另一个宏from_json!,它可以让我摆脱类似的r#""#东西

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

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

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

我怎么from_json去上班?

4

2 回答 2

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);
}

尽管您可能希望将StringContent枚举重写为从 a 构建serde_json::Value,因为它已经为您巧妙地解析了。

于 2017-11-15T16:09:20.787 回答
3

我只使用jsonserde_json 提供的宏,它适用于您的确切语法:

#[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
        }
    });
}

这将创建一个Value结构。如果由于某种原因您确实需要将其作为字符串返回,则需要使用它的Display实现重新序列化它:

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)
}
于 2017-11-15T16:10:20.480 回答