如何进行模式匹配以获得 serde_json 已解析的数字?
How can I pattern match to get at the numbers that serde_json has parsed?
我想将第 3 方库枚举与 JSON 相互转换。因为我不想编辑第 3 方源代码,所以我不想使用派生宏。
我想手写serde_jsondeserialize
方法。我认为模式匹配是可行的方法,但我需要匹配的东西不是 public:
extern crate serde_json;
#[test]
fn test_parse_from_json() {
let s = r#"{
"e": 0,
"c": 1,
"n": 2
}"#;
let v: Map<String, Value> = serde_json::from_str(&s).unwrap();
match (&v["e"], &v["c"], &v["n"]) {
(&Value::Number(ref e), &Value::Number(ref c), &Value::Number(ref n)) => {
// e is a PosInt(u64) but that isn't public to match one nor access its methods!
let value = e.n; // error[E0616]: field `n` of struct `serde_json::Number` is private
}
_ => (),
}
}
无法编译。如果我用我可以设置断点的东西替换那个内部位,我可以在调试器中看到 e
是一个包含 PosInt(0)
的 Number
。
您不能对私有字段进行模式匹配,因为它们是私有的。您必须使用图书馆决定提供的访问器。 Number
shows that it has methods like as_u64
的 serde_json 文档:
let value = e.as_u64().expect("not a u64");
As I don't want to edit the 3rd party source code I don't want to use the derive macros.
您可能正在遭受X-Y problem. For example, the Serde docs describe how to implement the traits for a "remote type"的困扰。
您还可以创建自己的反序列化类型,并构建与库类型之间的转换:
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
#[derive(Deserialize)]
struct Mine {
e: u64,
c: u64,
n: u64,
}
#[test]
fn test_parse_from_json() {
let s = r#"{
"e": 0,
"c": 1,
"n": 2
}"#;
let v: Mine = serde_json::from_str(&s).unwrap();
println!("{:?}", (v.e, v.c, v.n));
}
根据@Shepmaster 的回答,我得到了更多信息:
let v: Map<String, Value> = serde_json::from_str(&s).unwrap();
let bn: Option<BallotNumber>;
match (&v["e"],&v["c"],&v["n"]) {
(&Value::Number(ref e),&Value::Number(ref c),&Value::Number(ref n)) => {
match ( &e.as_u64(), &c.as_u64(), &n.as_u64() ) {
(&Some(era), &Some(count), &Some(number)) =>
bn = Some(BallotNumber::new(era, count, number)),
_ =>
bn = None
}
},
_ =>
bn = None
}
这只是它看起来有点像火车撞车而已。鉴于@Shepmaster 的回答指出 serde 提供了一种绕过孤儿规则的方法,我将使用该方法。
我想将第 3 方库枚举与 JSON 相互转换。因为我不想编辑第 3 方源代码,所以我不想使用派生宏。
我想手写serde_jsondeserialize
方法。我认为模式匹配是可行的方法,但我需要匹配的东西不是 public:
extern crate serde_json;
#[test]
fn test_parse_from_json() {
let s = r#"{
"e": 0,
"c": 1,
"n": 2
}"#;
let v: Map<String, Value> = serde_json::from_str(&s).unwrap();
match (&v["e"], &v["c"], &v["n"]) {
(&Value::Number(ref e), &Value::Number(ref c), &Value::Number(ref n)) => {
// e is a PosInt(u64) but that isn't public to match one nor access its methods!
let value = e.n; // error[E0616]: field `n` of struct `serde_json::Number` is private
}
_ => (),
}
}
无法编译。如果我用我可以设置断点的东西替换那个内部位,我可以在调试器中看到 e
是一个包含 PosInt(0)
的 Number
。
您不能对私有字段进行模式匹配,因为它们是私有的。您必须使用图书馆决定提供的访问器。 Number
shows that it has methods like as_u64
的 serde_json 文档:
let value = e.as_u64().expect("not a u64");
As I don't want to edit the 3rd party source code I don't want to use the derive macros.
您可能正在遭受X-Y problem. For example, the Serde docs describe how to implement the traits for a "remote type"的困扰。
您还可以创建自己的反序列化类型,并构建与库类型之间的转换:
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
#[derive(Deserialize)]
struct Mine {
e: u64,
c: u64,
n: u64,
}
#[test]
fn test_parse_from_json() {
let s = r#"{
"e": 0,
"c": 1,
"n": 2
}"#;
let v: Mine = serde_json::from_str(&s).unwrap();
println!("{:?}", (v.e, v.c, v.n));
}
根据@Shepmaster 的回答,我得到了更多信息:
let v: Map<String, Value> = serde_json::from_str(&s).unwrap();
let bn: Option<BallotNumber>;
match (&v["e"],&v["c"],&v["n"]) {
(&Value::Number(ref e),&Value::Number(ref c),&Value::Number(ref n)) => {
match ( &e.as_u64(), &c.as_u64(), &n.as_u64() ) {
(&Some(era), &Some(count), &Some(number)) =>
bn = Some(BallotNumber::new(era, count, number)),
_ =>
bn = None
}
},
_ =>
bn = None
}
这只是它看起来有点像火车撞车而已。鉴于@Shepmaster 的回答指出 serde 提供了一种绕过孤儿规则的方法,我将使用该方法。