I want to convert 3rd party library enums to and from JSON. As I don't want to edit the 3rd party source code I don't want to use the derive macros.
I want to handwrite the serde_json deserialize method. I am thinking that pattern matching is the way to go but the things I need to match on are not 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
}
_ => (),
}
}
That doesn't compile. If I replace that inner bit with something I can set a breakpoint on, I can see in the debugger that e is a Number which contains a PosInt(0).
You cannot pattern match on private fields because they are private. You have to use the accessors the library decides to provide. The serde_json documentation for Number shows that it has methods like as_u64:
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.
You may be suffering from the X-Y problem. For example, the Serde docs describe how to implement the traits for a "remote type".
You could also create your own type that you deserialize into and construct a transformation to and from the library 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));
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With