Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert serde_json::Value into concrete type implementing Deserialize trait?

Tags:

json

rust

I am writing a websocket server which deserializes incoming frames into a serde_json::Value and then passes this value to (potentially many) callbacks. I would like the callbacks to convert the serde_json::Value to a new type (e.g. MyType in the example below) without an encode/decode pass. It seems to me that the serde machinery should have enough information to do this (with the possibility of an error if the contained fields and types do not match). In the example below, the function to_my_type() stands in for this callback function. Is is the encode/decode that I want to bypass from this function.

I could of course pass the raw encoded data to each callback, but then each callback will have to do the decoding separately. I want to keep the function signature of the callbacks taking an argument of type serde_json::Value so that different callbacks can get different types but that I can register them all with a common function signature.

#![feature(proc_macro)]

#[macro_use]
extern crate serde_derive;
extern crate serde_json;

#[derive(Serialize, Deserialize)]
struct MyType {
    a: bool,
}

fn as_json(a: &MyType) -> serde_json::Value {
    let buf = serde_json::to_vec(a).unwrap();
    serde_json::from_slice::<serde_json::Value>(&buf).unwrap()
}

fn to_my_type(value: serde_json::Value) -> MyType {
    // How to convert a serde_json::Value into MyType without encode/decode pass?
    let buf = serde_json::to_vec(&value).unwrap();
    serde_json::from_slice::<MyType>(&buf).unwrap()
}

fn main() {
    let store = MyType{a: true};
    let raw_json = as_json(&store);
    let _store2 = to_my_type(raw_json);
}
like image 843
Andrew Straw Avatar asked Jan 18 '17 11:01

Andrew Straw


1 Answers

You can use the serde_json::from_value function to convert a Value to any type that implements Deserialize:

fn to_my_type(value: serde_json::Value) -> MyType {
    serde_json::from_value(value).unwrap()
}
like image 165
oli_obk Avatar answered Oct 13 '22 04:10

oli_obk