Skip to main content

SerializeDict

Derive Macro SerializeDict 

Source
#[derive(SerializeDict)]
{
    // Attributes available to this derive:
    #[zbus]
    #[zvariant]
}
Expand description

Adds Serialize implementation to structs to be serialized as a D-Bus dictionary type.

The dictionary type is determined by the signature attribute. The default is a{sv} (string keys, variant values), but nested forms like a{sa{sv}} and a{oa{sv}} are also supported — fields whose value type is itself a dict (or any non-Variant type) are serialized directly through their own Serialize impl rather than wrapped as a variant.

Such dictionary types are very commonly used with D-Bus and GVariant.

§Alternative Approaches

There are two approaches to serializing structs as dictionaries:

  1. Using this macro (simpler, but less control).
  2. Using the Serialize derive with zvariant::as_value (more verbose, but more control).

See the example below and the relevant FAQ entry in our book for more details on the alternative approach.

§Example

§Approach #1

use zvariant::{SerializeDict, Type};

#[derive(Debug, Default, SerializeDict, Type)]
#[zvariant(signature = "a{sv}", rename_all = "PascalCase")]
pub struct MyStruct {
    field1: Option<u32>,
    field2: String,
}

§Approach #2

use serde::Serialize;
use zvariant::{Type, as_value};

#[derive(Debug, Default, Serialize, Type)]
#[zvariant(signature = "a{sv}")]
#[serde(default, rename_all = "PascalCase")]
pub struct MyStruct {
    #[serde(with = "as_value::optional", skip_serializing_if = "Option::is_none")]
    field1: Option<u32>,
    #[serde(with = "as_value")]
    field2: String,
}

§Nested dictionaries

To represent shapes like a{sa{sv}} (the body type of org.freedesktop.DBus.ObjectManager.GetManagedObjects and similar APIs), nest one SerializeDict/DeserializeDict struct inside another:

use zvariant::{DeserializeDict, SerializeDict, Type};

#[derive(SerializeDict, DeserializeDict, Type, Default)]
#[zvariant(signature = "a{sv}", rename_all = "PascalCase")]
pub struct AdapterProperties {
    address: Option<String>,
    name: Option<String>,
}

#[derive(SerializeDict, DeserializeDict, Type, Default)]
#[zvariant(signature = "a{sa{sv}}")]
pub struct InterfaceProperties {
    #[zvariant(rename = "org.bluez.Adapter1")]
    adapter: Option<AdapterProperties>,
}

§Custom crate path

If you’ve renamed zvariant in your Cargo.toml or are using it through a re-export, you can specify the crate path using the crate attribute:

use zvariant::{SerializeDict, Type};

#[derive(SerializeDict, Type)]
#[zvariant(signature = "a{sv}", crate = "zvariant")]
struct MyStruct {
    field: String,
}