如何将以下 from_str 宏更改为 from_json?
How do I change the following from_str macro to from_json?
我有以下宏。请注意,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
工作?
您的宏不起作用,因为 concat!
不能用于以语法上合理的方式将标识符相互附加。它而是将标识符连接成一个字符串。你现在看起来像 "r#\" ~your JSON~ \"#"
,其中 r#
和 #
是文字字符。
您的方法在 a stabilized, extended concat_idents!
is implemented 之前不会奏效。
您必须在宏中手动解析 JSON 语法。如需灵感,请查看 how Serde does it.
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
枚举以从 serde_json::Value
构建,因为它已经为您巧妙地解析了。
我只使用 json
macro provided by serde_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)
}
我有以下宏。请注意,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
工作?
您的宏不起作用,因为 concat!
不能用于以语法上合理的方式将标识符相互附加。它而是将标识符连接成一个字符串。你现在看起来像 "r#\" ~your JSON~ \"#"
,其中 r#
和 #
是文字字符。
您的方法在 a stabilized, extended concat_idents!
is implemented 之前不会奏效。
您必须在宏中手动解析 JSON 语法。如需灵感,请查看 how Serde does it.
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
枚举以从 serde_json::Value
构建,因为它已经为您巧妙地解析了。
我只使用 json
macro provided by serde_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)
}