Is there a way to specify prefix fields in serde?

I've this in Cargo.toml:

[rialight.application]
id = "com.qux.foo"
title = "Untitled Application"

[[rialight.install-files]]
match = "res/lang/**/*.json"

That's how it's serialized/deserialized currently:

#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct ApplicationConfig {
    #[serde(rename = "id")]
    pub id: String,
    #[serde(rename = "title")]
    pub title: String,
}

// ...
let application_config: ApplicationConfig = toml::from_str(std::str::from_utf8(&fs::read(application_config_path).unwrap()).unwrap()).unwrap();
// ...

There's a problem here: id and title are extracted from the root, I suppose. Is there a way to directly specify that id and title belong to rialight.application? Or do I need a dynamic access to skip rialight.application?

Serde will by default follow any nested structure in your statically-typed domain types. If you wrap your ApplicationConfig accordingly, behind the appropriate fields, then the deserializer will look for it under that path. Playground.

2 Likes

The serde way is creating two wrapper structs to model the same data hierarchy of your toml file with your Rust structs. This allows you to serialize the data back.

pub struct Config {
    rialight: RialightConfig,
}
pub struct RialightConfig {
    application: ApplicationConfig
}
pub struct ApplicationConfig {
    // ...
}

If you need deserialization only you can use serde_query.

#[derive(serde_query::Deserialize)]
pub struct ApplicationConfig {
    #[query(".rialight.application.id")]
    pub id: String,
}
2 Likes

Side note: 3rd party configuration in Cargo.toml should live underneath the [package.metadata] table.

2 Likes

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.