Serde and error handling

Is there any way to just tell serde to ignore errors when deserializing? E.g. for something like

/// The main data structure for deserializing with serde.
#[derive(Deserialize)]
struct SerdeDataSourceHelper {
    title: Option<String>,
    base_url: Option<String>, // ???
    projects: Option<BTreeMap<String, BTreeMap<Url, BTreeMap<String, SerdeForkOptions>>>>,
    repo_list_srcs: Option<Vec<SerdeRepoList>>,
    project: Option<BTreeMap<String, SerdeProjectOptions>>,
}

/// The options for a given fork.
#[derive(Deserialize)]
struct SerdeForkOptions {
    active: bool,
    federate: bool,
}

/// A repo list.
#[derive(Deserialize)]
struct SerdeRepoList {
    url: Url,
    active: bool,
    allow_negative_entries: bool,
}

/// The options for a given project (all forks).
#[derive(Deserialize)]
struct SerdeProjectOptions {
    active: bool,
}

is there any way to tell serde to just... ignore stuff that doesn't match the expectation? So if someone shoved a list where a deeper level of the BTreeMap was expected it'd just ignore that list entirely, etc etc?

Maybe something with using an untagged wrapper enum...? Surely there's a better way of doing this? .-.

What about creating your own MaybeInvalid<T> wrapper type?

#[derive(Debug)]
enum MaybeInvalid<T> {
    Valid(T),
    Invalid,
}

impl<'de, T> Deserialize<'de> for MaybeInvalid<T>
where
    T: Deserialize<'de>,
{
    fn deserialize<D: Deserializer<'de>>(de: D) -> Result<Self, D::Error> {
        match T::deserialize(de) {
            Ok(valid) => Ok(MaybeInvalid::Valid(valid)),
            Err(_) => Ok(MaybeInvalid::Invalid),
        }
    }
}

(playground)

3 Likes

So instead of Option<T> we'd use... hm...

Say, why's there no Result<T, ()> serialization, equivalent to Option<T> but discards deserialization errors? Seems like it could be useful for error management.

Well Option<T> means either you have a T or it's not present, which is very different from "I have a T or something which is invalid".

Using Result<T, ()> for this would be incompatible with serde's existing blanket impl. Defining a meaningful, specific wrapper type seems better in pretty much every way.

2 Likes

Well what do you call "I have a T or I don't care what I have"? That's basically the same as Option...

Not at all. Option indicates the absence of something whereas your "I don't care what I have" can mean the item is not present or not valid.

2 Likes

Not being present can be a form of not being valid, tho. And vice-versa.

Rust and crates are always failing error handling...

You are, as always, free to send pull requests to projects.

2 Likes