| Crates.io | lenient_derive |
| lib.rs | lenient_derive |
| version | 0.1.2 |
| created_at | 2025-06-04 20:22:59.682091+00 |
| updated_at | 2025-06-05 18:29:22.875757+00 |
| description | A procedural macro to derive fault-tolerant Serde deserialization using #[lenient] and #[optional] annotations. |
| homepage | |
| repository | https://github.com/masumeebhami/lenient |
| max_upload_size | |
| id | 1700849 |
| size | 7,414 |
This crate provides the #[derive(LenientDeserialize)] procedural macro to enable fault-tolerant Serde deserialization for struct fields in Rust.
It is designed to work in conjunction with the lenient crate, which defines wrappers for lenient field handling using serde.
#[derive(LenientDeserialize)] for struct-level deserialization#[lenient] to fallback to default on deserialization failure#[optional] to fallback to None on failureLenient<T> and Optional<T> wrappersDeserialize for the annotated structIn your Cargo.toml:
[dependencies]
lenient = "0.1"
In your Rust code:
use lenient_derive::LenientDeserialize;
use serde::Deserialize;
#[derive(Debug, Default)]
struct Age(pub u32);
impl<'de> Deserialize<'de> for Age {
fn deserialize<D>(de: D) -> Result<Self, D::Error>
where D: serde::Deserializer<'de> {
Ok(Age(u32::deserialize(de)?))
}
}
#[derive(Debug, Default)]
struct Score(pub u8);
impl<'de> Deserialize<'de> for Score {
fn deserialize<D>(de: D) -> Result<Self, D::Error>
where D: serde::Deserializer<'de> {
Ok(Score(u8::deserialize(de)?))
}
}
#[derive(Debug, Default, LenientDeserialize)]
struct UserProfile {
#[lenient]
age: Age,
#[optional]
score: Score,
#[lenient]
nickname: String,
}
The macro generates an internal deserialization wrapper struct like:
#[derive(Deserialize)]
struct UserProfileInternal {
#[serde(default)]
age: Lenient<Age>,
#[serde(default)]
score: Optional<Score>,
#[serde(default)]
nickname: Lenient<String>,
}
Then it provides a Deserialize implementation for the outer struct using the inner one.
MIT