How to Serialize Arc<Mutex<T>> in Rust?

Viewed 89

I have a trait DataSet, for which I've implemented Serialize like so:

impl Serialize for dyn DataSet {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let mut seq = serializer.serialize_map(Some(2))?;
        seq.serialize_entry("fields", "Hello")?;
        seq.serialize_entry("measures", "There")?;
        seq.end()
    }
}

Now, in program/application I am sharing pointer to the trait object:

let x: Arc<Mutex<dyn DataSet>> = Arc::new(Mutex::new(data));

Where data is any object which implements DataSet.

Now, I want to turn this object into json (ie serialize it):

serde_json::to_string(&x)

It works for Box instead of Arc<Mutex<>>. But with Arc<Mutex<>> compiler complains:

the size for values of type `dyn base_engine::DataSet` cannot be known at compilation time
the trait `Sized` is not implemented for `dyn base_engine::DataSet`
the trait `Serialize` is implemented for `Arc<T>`
required because of the requirements on the impl of `Serialize` for `Mutex<dyn base_engine::DataSet>`

I've tried adding feature ["rc"] to serde, but this didn't help.

1 Answers

Update: Since serde 1.0.145 this code works.


Original answer:

Serde doesn't support serializing a Mutex with unsized type. I sent a PR to relax this, but in the meantime you can use a newtype:

pub struct MutexWrapper<T: ?Sized>(pub Mutex<T>);

impl<T: ?Sized + Serialize> Serialize for MutexWrapper<T> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        self.0
            .lock()
            .expect("mutex is poisoned")
            .serialize(serializer)
    }
}

let x: Arc<MutexWrapper<dyn DataSet>> = Arc::new(MutexWrapper(Mutex::new(data)));

You still need to enable the rc feature of serde, of course.

Related