You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用serde::from_value反序列化泛型结构体?

问题:泛型结构体反序列化编译失败

尝试将API的JSON响应反序列化为泛型结构体,但代码无法编译,原代码如下:

use serde::Deserialize;
use serde_json; // 1.0.102

#[derive(Deserialize)]
struct ApiResult<T> {
    pub data: T,
    pub status: String
}

fn get_result<T>(json: serde_json::Value) -> Result<ApiResult<T>, anyhow::Error> {
    let r: ApiResult<T> = serde_json::from_value(json)?;
    Ok(r)
}

fn main() -> Result<(),anyhow::Error> {
    let json = serde_json::json!({
        "data": 1,
        "status": "ok"
    });
    
    let r2: ApiResult<i64> = get_result::<i64>(json).unwrap();
    
    Ok(())
}

编译时出现以下错误:

Compiling playground v0.0.1 (/playground)
error[E0277]: the trait bound `T: Deserialize<'_>` is not satisfied
   --> src/main.rs:11:27
    |
11  |     let r: ApiResult<T> = serde_json::from_value(json)?;
    |                           ^^^^^^^^^^^^^^^^^^^^^^ the trait `Deserialize<'_>` is not implemented for `T`
    |
note: required for `ApiResult<T>` to implement `for<'de> Deserialize<'de>`
   --> src/main.rs:4:10
    |
4   | #[derive(Deserialize)]
    |          ^^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
5   | struct ApiResult<T> {
    |        ^^^^^^^^^^^^
= note: required for `ApiResult<T>` to implement `DeserializeOwned`
note: required by a bound in `from_value`
   --> /playground/.cargo/registry/src/index.crates.io-6f17d22bba15001f/serde_json-1.0.102/src/value/mod.rs:983:8
    |
981 | pub fn from_value<T>(value: Value) -> Result<T, Error>
    |        ---------- required by a bound in this function
982 | where
983 |     T: DeserializeOwned,
    |        ^^^^^^^^^^^^^^^^ required by this bound in `from_value`
= note: this error originates in the derive macro `Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider restricting type parameter `T`
    |
10  | fn get_result<T: _::_serde::Deserialize<'_>>(json: serde_json::Value) -> Result<ApiResult<T>, anyhow::Error> {
    |                ++++++++++++++++++++++++++++

For more information about this error, try `rustc --explain E0277`.
error: could not compile `playground` (bin "playground") due to previous error

修复方案

错误核心是get_result函数的泛型参数T缺少必要的 trait 约束:

  • serde_json::from_value要求目标类型实现DeserializeOwned,而ApiResult<T>要满足这个 trait,其内部的T必须支持反序列化(即实现for<'de> Deserialize<'de>)。

只需给get_result的泛型T添加约束即可修复,有两种等价写法:

写法一:使用DeserializeOwned约束

use serde::Deserialize;
use serde_json; // 1.0.102
use serde::de::DeserializeOwned;

#[derive(Deserialize)]
struct ApiResult<T> {
    pub data: T,
    pub status: String
}

// 添加DeserializeOwned约束
fn get_result<T: DeserializeOwned>(json: serde_json::Value) -> Result<ApiResult<T>, anyhow::Error> {
    let r: ApiResult<T> = serde_json::from_value(json)?;
    Ok(r)
}

fn main() -> Result<(),anyhow::Error> {
    let json = serde_json::json!({
        "data": 1,
        "status": "ok"
    });
    
    let r2: ApiResult<i64> = get_result::<i64>(json).unwrap();
    
    Ok(())
}

写法二:直接使用生命周期约束

use serde::Deserialize;
use serde_json; // 1.0.102

#[derive(Deserialize)]
struct ApiResult<T> {
    pub data: T,
    pub status: String
}

// 添加for<'de> Deserialize<'de>约束
fn get_result<T: for<'de> Deserialize<'de>>(json: serde_json::Value) -> Result<ApiResult<T>, anyhow::Error> {
    let r: ApiResult<T> = serde_json::from_value(json)?;
    Ok(r)
}

fn main() -> Result<(),anyhow::Error> {
    let json = serde_json::json!({
        "data": 1,
        "status": "ok"
    });
    
    let r2: ApiResult<i64> = get_result::<i64>(json).unwrap();
    
    Ok(())
}

两种写法都能告诉编译器:T类型必须支持反序列化,从而让ApiResult<T>满足from_value的类型要求。

内容的提问来源于stack exchange,提问作者pielgrzym

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 18:15:06