Can I deserialize a object with no type annotation?

The following is the pseudo code when I serialize an object and then deserialize it:

let my_data = 1i32;
let my_data_ser = serde::Serialize(&my_data);
let my_data_de = serde::Deserialize::<i32>(my_data_ser);

When I do deserialize I need to add type annotation <i32> to serde::Deserialize::<i32>. But in the situation I am facing, there are many types that I can not write it down by hand. So is there a way I don't have to add type annotation? I found the mothod deserialize_any, would it be a relevant solution?

The deserializer has to be given the type — otherwise it cannot know what to create from the data — but you may be able to get the type from some (compile time) context rather than writing it out. Can you give a larger code sample showing how this deserialization is going to be used, and more description of your program's goal?

2 Likes

Thanks for your reply.
The following is the larger code sample I am facing:

In some day, I save some data need to save in local files:

use std::io::{BufWriter, BufReader};
use serde::{Serialize, Deserialize, de::DeserializeOwned};
use bincode;

pub fn sof<T: Serialize>(data: &T, name: &str, path: &str) {
    let full_path = path.to_owned() + "/" + name;
    let w = std::fs::File::create(full_path).unwrap();
    let mut f = BufWriter::new(w);
    bincode::serialize_into(&mut f, &data).unwrap();
}

pub fn rof<T: DeserializeOwned>(name: &str, path: &str) -> T {
    let full_path = path.to_owned() + "/" + name;
    let r = std::fs::File::open(full_path).unwrap();
    let mut f = BufReader::new(r);
    let res: T = bincode::deserialize_from::<&mut BufReader<std::fs::File>, T>(&mut f).unwrap();
    res
}

pub trait Sof: Serialize
where
    for<'a> Self: Deserialize<'a>,
{
    fn sof(&self, name: &str, path: &str) { sof(self, name, path); }
    fn rof(name: &str, path: &str) -> Self { rof::<Self>(name, path) }
}

impl<T> Sof for T
where
    for<'a> T: Serialize + Deserialize<'a>,
{}

#[derive(Serialize, Deserialize)]
struct MyType1;
#[derive(Serialize, Deserialize)]
struct MyType2;

fn main() {
    let my_data_i32 = 1i32;
    let my_data_f32 = 1f32;
    let my_data_type1 = MyType1;
    let my_data_type2 = MyType2;

    my_data_i32.sof("data1", "D:/data_save");
    my_data_f32.sof("data2", "D:/data_save");
    my_data_type1.sof("data3", "D:/data_save");
    my_data_type2.sof("data4", "D:/data_save");
}

And in another day, I need to read the saved files out:

fn main {
    let data1 = rof::<i32>("data1", "D:/data_save");
    let data2 = rof::<f32>("data2", "D:/data_save");
    let data3 = rof::<MyType1>("data3", "D:/data_save");
    let data4 = rof::<MyType2>("data4", "D:/data_save");
}

If you have many values to work with together like this, then declare a struct for them.

struct MyData {
    i: i32,
    f: f32,
    t1: MyType1,
    t2: MyType2,
}

Then you can serialize and deserialize them all together only using the MyData struct type.

let data = rof::<MyData>("all_data", "D:/data_save");

Or, if it is important that they be written to separate files, then you can still use the struct to help you serialize and deserialize the parts with the correct types.

fn main() {
    let data = MyData {
        i: rof("data1", "D:/data_save"),
        f: rof("data2", "D:/data_save"),
        t1: rof("data3", "D:/data_save"),
        t2: rof("data4", "D:/data_save"),
    };
}

When rof() is called with the result being put in a field of the struct, type inference figures out what the T type to deserialize must be.

2 Likes

There are many types like MyType, in fact, they are kind of hierarc generic type like:

struct MyTypeLayer1_1;
struct MyTypeLayer1_2;

struct MyTypeLayer2_1<T>(T);
struct MyTypeLayer2_2<T>(T);

And the amount of MyType is keeping grow with the project going, so it would be impossilbe to write the possible types on MyData.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.