generic serde_json deserialize function for strongly typed objects

Viewed 178

This function is from the serde_json docs :

fn read_user_from_file<P: AsRef<Path>>(path: P) -> Result<User, Box<dyn Error>> {
    // Open the file in read-only mode with buffer.
    let file = File::open(path)?;
    let reader = BufReader::new(file);

    // Read the JSON contents of the file as an instance of `User`.
    let u = serde_json::from_reader(reader)?;

    // Return the `User`.
    Ok(u)
}

I want to make it more generic so I can deserialize to any typed object. Then, I can use the function for multiple objects.

fn read_user_from_file<T,P: AsRef<Path>>(path: P) -> Result<T, Box<dyn Error>> {
    // Open the file in read-only mode with buffer.
    let file = File::open(path)?;
    let reader = BufReader::new(file);

    let t:T = serde_json::from_reader(reader)?;

    // Return the `User`.
    Ok(t)
}

However The error message on the serde_json::from_reader line is :

the trait bound for<'de> T: models::_::_serde::Deserialize<'de> is not satisfied required because of the requirements on the impl of DeserializeOwned for TrustcE0277 lib.rs(1, 1): required by a bound in this de.rs(2500, 8): required by this bound in from_reader blocks.rs(62, 17): consider restricting type parameter T

1 Answers

You can't deserialize into "any typed object", only into one which implements either Deserialize<'de> or DeserializeOwned.

As you don't keep around the JSON, you want to use DeserializeOwned:

fn read_user_from_file<T, P>(path: P) -> Result<T, Box<dyn Error>>
where
    T: DeserializeOwned,
    P: AsRef<Path>,
{
    // Open the file in read-only mode with buffer.
    let file = File::open(path)?;
    let reader = BufReader::new(file);

    let t:T = serde_json::from_reader(reader)?;

    // Return the `User`.
    Ok(t)
}
Related