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 theextern crater serde
是防御性编程(因为它是serde_派生所必需的),所以只要我有其他serde板条箱在使用,我就会将它包括在内。这听起来很合理。@JanNilsFerner这就是我最后要做的。我还包括了serde json!宏在我自己的范围内实现我的目标。我现在看到的唯一负面影响是,除了在我的板条箱上执行相同的操作外,我还必须在extern板条箱serde_json上执行#[macro_use],因为这两个宏都是必需的。我想我现在不得不接受这个。谢谢你的支持。