有没有一种方法可以像反序列化一样派生结构以从 serde_json::Value 获得自动转换?

Is there a way to derive a struct like with Deserialize to get automatic transform from serde_json::Value?

从字符串直接反序列化为结构非常有效。但在某些情况下,您可能已经有了一个 serde_json::Value,并想尝试将其转换为结构。

以下示例说明了这一点:从 JSON(例如在网络库中)加载一个 Request 结构,使用类型字符串和通用内容作为值,然后您想要调用处理程序(来自客户端库)并将值转换为给定结构。

use serde::Deserialize;
use serde_json::{json, Value};
use std::convert::TryFrom;
use std::error::Error;

#[derive(Deserialize)]
struct Request {
    #[serde(alias = "type")]
    req_type: String,
    content: Value
}

#[derive(Deserialize)]
struct Person {
    name: String,
    age: u8
}

// It there a way to avoid having to declare this???
impl TryFrom<Value> for Person {
    type Error = serde_json::Error;

    fn try_from(value: Value) -> Result<Self, Self::Error> {
        Person::deserialize(value)
    }
}

fn say_hello(p: Person) {
    println!("Hello, I'm {}, and I'm {} years old!", p.name, p.age);
}

fn main() -> Result<(), Box<dyn Error>> {
    let req: Request = Request::deserialize(json!({
        "type": "sayHello",
        "content": {
            "name": "Pierre",
            "age": 32
        }
    }))?;

    match req.req_type.as_str() {
        "sayHello" => say_hello(req.content.try_into()?),
        _ => println!("unknown request")
    }

    Ok(())
}

所以问题是:是否实施了一些 derive 或其他魔术,允许与 String 中的 Deserialize 相同的行为,以便客户端只能写:

#[derive(Deserialize)]
struct Person {
    name: String,
    age: u8
}

fn say_hello(p: Person) {
    println!("Hello, I'm {}, and I'm {} years old!", p.name, p.age);
}

我尝试了 #[serde(try_from = "Value")] 属性,但它看起来不像是为此目的而设计的...

serde_json::from_value()专门针对这个:

pub fn from_value<T>(value: Value) -> Result<T, Error> 
where
    T: DeserializeOwned, 

给定任何 serde_json::Value 和一些 T: DeserializedOwned,如果可能,该函数会将 Value 反序列化为那个 T