Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Generic type that implements DeserializeOwned

Below is a non-functioning code example:

use serde_json::json;

#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Model<T>
where
    T: DeserializeOwned,
{
    pub id: i32,
    pub info: Option<T>,
}

fn main() {
    #[derive(Serialize, Deserialize, Debug, Clone)]
    struct Info {
        name: String,
    }

    let some_model_1: Model<Info> = serde_json::from_value(json!({
        "id": 43,
        "info": {
            "name": "some_model_name"
        }
    }))
    .unwrap();

    println!("some_model_1: {:#?}", some_model_1);

    let some_model_2: Model<Info> = serde_json::from_value(json!({
        "id": 43
    }))
    .unwrap();

    println!("some_model_2: {:#?}", some_model_2);
}

The error is as follows: cannot satisfy 'T: Deserialize<'de>.

So I have added:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

#[serde(deserialize_with = "Option::deserialize")]
pub info: Option<T>,

Now the code compiles, but the missing "info" object for some_model_2 causes an error despite using the Option type:

thread 'main' panicked at 'called 'Result::unwrap()' on an 'Err' value: Error("missing field 'info'", line: 0, column: 0)', src\main.rs:34:6

My last solution was to use a custom function to do the deserialization for the info field:

use serde::{de::DeserializeOwned, Deserialize, Deserializer, Serialize};
use serde_json::{json, Value};

#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Model<T>
where
    T: DeserializeOwned,
{
    pub id: i32,

    #[serde(deserialize_with = "ok_or_none")]
    pub info: Option<T>,
}

fn ok_or_none<'de, D, T>(deserializer: D) -> Result<Option<T>, D::Error>
where
    D: Deserializer<'de>,
    T: Deserialize<'de>,
{
    let v = Value::deserialize(deserializer)?;
    Ok(T::deserialize(v).ok())
}

fn main() {
    #[derive(Serialize, Deserialize, Debug, Clone)]
    struct Info {
        name: String,
    }

    let some_model_1: Model<Info> = serde_json::from_value(json!({
        "id": 43,
        "info": {
            "name": "some_model_name"
        }
    }))
    .unwrap();

    println!("some_model_1: {:#?}", some_model_1);

    let some_model_2: Model<Info> = serde_json::from_value(json!({
        "id": 43
    }))
    .unwrap();

    println!("some_model_2: {:#?}", some_model_2);
}

This change did not help, the same panic bug remains. The ok_or_none function is not even called.

Below are my dependencies:

serde = { version = "1.0.94", features = ["derive"]  }
serde_json = "1.0.40"

I don’t know what else I can do to make this work.

Thank you in advance for your help!

>Solution :

You don’t need to use DeserializeOwned, a plain T is enough, when deriving from serde it will check that your attributes can be serialized/deserialized:

use serde::{Deserialize, Serialize};
use serde_json::json;

#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Model<T> {
    pub id: i32,
    pub info: Option<T>,
}

fn main() {
    #[derive(Serialize, Deserialize, Debug, Clone)]
    struct Info {
        name: String,
    }

    let some_model_1: Model<Info> = serde_json::from_value(json!({
        "id": 43,
        "info": {
            "name": "some_model_name"
        }
    }))
    .unwrap();

    println!("some_model_1: {:#?}", some_model_1);

    let some_model_2: Model<Info> = serde_json::from_value(json!({
        "id": 43
    }))
    .unwrap();

    println!("some_model_2: {:#?}", some_model_2);
}

Playground

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading