Rust 如何将以下内容从\u str宏更改为从\u json?

Rust 如何将以下内容从\u str宏更改为从\u json?,rust,rust-macros,Rust,Rust Macros,我有以下宏。请注意,StringContent是一个枚举项 #[macro_export] macro_rules! from_str { ($json:expr) => { StringContent(String::from($json)) } } 这样我就可以像这样编写代码了 from_str!(r#"{ "appName": "Demo App", "appVersion": "1.0", "datab

我有以下宏。请注意,
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
    }
}"#)
现在我想从_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#"#"#)))
    }
}

我怎样才能从json获取
来工作呢?

您的宏无法工作,因为
concat
不能用于以语法上合理的方式相互追加标识符。它将标识符连接到一个字符串中。您的代码现在看起来像
“r\35;\”~ your JSON~ \“
,其中
r\35;
是文字字符

你的方法要到下一步才会奏效

您必须在宏中手动解析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);
}
尽管您可能希望重写从
serde_json::Value
构建的
StringContent
enum,因为它已经为您进行了整洁的解析。

我只想使用,它与您的确切语法一起工作:

#[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
        }
    });
}
这将创建一个结构。如果出于某种原因确实需要将其作为字符串返回,则需要使用它的
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)
}

好了,你不能用concat!因为它将生成一个以字符“r”和“#”开头的字符串,而不是实际替换您想要的任何内容。还有,包括!将包括实际的文件,这绝对不是你想在这里做的。你为什么用那个宏?您是否计划创建一个包含转义文本的文件,然后再次解析它?@JanNilsFerner感谢您的洞察力。我编辑了我的答案以删除包含!还有改进的海螺!使用一点。但似乎仍然不起作用。这就把事情弄清楚了。不幸的是,您的方法仍然不起作用,有关原因的详细信息,请参见我的答案。请注意,您不需要包含
serde
本身,只需要包含
serde_json
。此外,OP希望使用
&str
,而不是
serde_json::Value
,尽管他可能应该重新考虑这一点。@JanNilsFerner the
extern crater serde
是防御性编程(因为它是serde_派生所必需的),所以只要我有其他serde板条箱在使用,我就会将它包括在内。这听起来很合理。@JanNilsFerner这就是我最后要做的。我还包括了serde json!宏在我自己的范围内实现我的目标。我现在看到的唯一负面影响是,除了在我的板条箱上执行相同的操作外,我还必须在extern板条箱serde_json上执行#[macro_use],因为这两个宏都是必需的。我想我现在不得不接受这个。谢谢你的支持。