我如何模式匹配以获得serde_json已解析的数字?

时间:2017-07-21 18:35:05

标签: json rust serde

我想将第三方库枚举转换为JSON和从JSON转换。因为我不想编辑第三方源代码,所以我不想使用派生宏。

我想手写serde_json deserialize方法。我认为模式匹配是要走的路,但我需要匹配的东西不公开:

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
        }
        _ => (),
    }

}

那不编译。如果我用可以设置断点的东西替换那个内部位,我可以在调试器中看到eNumber,其中包含PosInt(0)

2 个答案:

答案 0 :(得分:1)

您不能在私有字段上进行模式匹配,因为它们是私有的。您必须使用库决定提供的访问器。 Number的serde_json文档显示它包含as_u64

等方法
let value = e.as_u64().expect("not a u64");
  

由于我不想编辑第三方源代码,所以我不想使用派生宏。

您可能会受到X-Y problem的影响。例如,Serde文档描述了如何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));
}

答案 1 :(得分:0)

根据@ 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提供了绕Orphan规则的方法,我将使用这种方法。