Is there ever a situation
Liar's paradox withstanding, saying something is always/never true is never correct. Even in math, at best something is true up to axioms. Now some things are "rarely" true/false (for some notion of "rarely"). So to literally answer your question, yes there exist situations.
Any time you have the possibility of not having a value that itself may not exist is a case for Option<Option<T>>
. Now there may be preferred ways to model that for one's taste. For example, the Clippy lint option_option
exists to dissuade one from having nested Option
s; however whatever you replace that with (e.g., a separate enum
) is functioning for what Option<Option<T>>
would suffice for. It's not too different than asking when should one distinguish among null
, an empty map/string, or the lack of key-value pair at all in JSON. There are times when one wants to distinguish among those three possibilities even if one normally wants to treat them equivalently.
The other case beyond intentionally having an Option<Option<T>>
that is arguably more common is when needing to satisfy a trait
's definition. You may have to wrap a generic thing in an Option
; but if the "thing" you have is already an Option
, then you're forced to generate a nested Option
.
If that's too much mumbo jumbo, then here is an explicit example relating it back to JSON. Let's say I have the following JSON schema:
{
"x": null | <string>,
"y": null | <bool>
}
I require x
and y
to exist. Why would I require them while still allowing for null
? If one sends a JSON map without one of the keys, then there's a chance they didn't even know that that is something I care about; but had they known, they would have sent that information. Unfortunately while I would like that data, there are times one may simply not have that info. By requiring one to explicitly send null
instead of omitting the key altogether, they at least "prove" to me that they know about this information I seek. They'll send null
when they don't have the data.
I require the keys to exist, so I need some way to detect if I received that key (e.g., Option<T>
). If after parsing the map, I have None
; then I know they didn't send the key and I'll error. If they do send the key but they send the value as null
, then I need a way to model that (e.g., Option<T>
). Combining both of those, we now see my local variable is Option<Option<T>>
. Or in code:
use core::fmt::{self, Formatter};
use serde::de::{Deserialize, Deserializer, Error, MapAccess, Visitor};
struct Foo {
x: Option<String>,
y: Option<bool>,
}
impl<'de> Deserialize<'de> for Foo {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct FooVisitor;
impl<'d> Visitor<'d> for FooVisitor {
type Value = Foo;
fn expecting(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
formatter.write_str("Foo")
}
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: MapAccess<'d>,
{
enum Field {
X,
Y,
}
impl<'e> Deserialize<'e> for Field {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'e>,
{
struct FieldVisitor;
impl Visitor<'_> for FieldVisitor {
type Value = Field;
fn expecting(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
write!(formatter, "'{X}' or '{Y}'")
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: Error,
{
match v {
X => Ok(Field::X),
Y => Ok(Field::Y),
_ => Err(E::unknown_field(v, FIELDS)),
}
}
}
deserializer.deserialize_identifier(FieldVisitor)
}
}
let mut x = None;
let mut y = None;
while let Some(key) = map.next_key()? {
match key {
Field::X => {
if x.is_some() {
return Err(Error::duplicate_field(X));
}
x = map.next_value().map(Some)?;
}
Field::Y => {
if y.is_some() {
return Err(Error::duplicate_field(Y));
}
y = map.next_value().map(Some)?;
}
}
}
x.ok_or_else(|| Error::missing_field(X)).and_then(|x| {
y.ok_or_else(|| Error::missing_field(Y))
.map(|y| Foo { x, y })
})
}
}
const X: &str = "x";
const Y: &str = "y";
const FIELDS: &[&str; 2] = &[X, Y];
deserializer.deserialize_struct("Foo", FIELDS, FooVisitor)
}
}
fn main() {
// This is bad since `x` is not sent.
let bad_json = "{\"y\":null}";
assert!(serde_json::from_str::<Foo>(bad_json).is_err());
// This is good since both `x` and `y` are sent even if the
// values are `null`.
let good_json = "{\"x\":null,\"y\":null}";
assert!(
serde_json::from_str::<Foo>(good_json)
.map_or(false, |foo| foo.x.is_none() && foo.y.is_none())
);
}
Of course there are literally an infinite number of examples including ones that justify the need for 100 nested Option
s; admittedly there is probably a better/more efficient way. The probability of you needing/wanting such a thing decreases the more nested Option
s you have though; but like almost anything, won't ever truly reach the probability of 0.