I want to deserialize API json response into a struct that uses generic type. Code below does not compile and I can't figure out how to make it work:
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(())
}
It produces an error:
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
In your get_result
function, you need to specify that the T
type is deserializable (T: for<'a> Deserialize<'a>
):
use serde::Deserialize;
use serde_json; // 1.0.102
#[derive(Deserialize)]
struct ApiResult<T> {
pub data: T,
pub status: String
}
fn get_result<T: for<'a> Deserialize<'a>>(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(())
}