Closed ggutoski closed 4 months ago
A pattern I'd recommend for this is having a separate "serde type" where you derive Serialize
/Deserialize
, and then impl TryFrom
to convert from the "serde type" to a validated struct. You can then have deserialize_with
decode to the "serde type" and then call TryFrom
A pattern I'd recommend for this is having a separate "serde type" ...
Thanks for the suggestion! This pattern is described in detail at https://github.com/serde-rs/serde/issues/642#issuecomment-683276351
TIL:
#[serde(try_from = "MyTypeShadow")]
Serde does not automatically validate deserialized structs. This is annoying because a struct instance that is otherwise guaranteed to be valid by construction can be made invalid via serde round trip. Examples in
tofn
includeGroupPublicInfo
andSharePublicInfo
.I spent a long time digging for ergonomic ways to validate serde-deserialized data. :disappointed: Seems like the best solution is to use
deserialize_with
as described here https://github.com/serde-rs/serde/pull/1858#pullrequestreview-575089757. Documentation ondeserialize_with
is sparse---this is all I could find: Field attributes · SerdeIf we do go this route then presumably the clean way to do it is for each struct would have a
validate()
method that is called in two places:new()
)deserialize_with
That's a pretty generic pattern---might even be worth a
Validator
trait or something. Note that this crate exists https://github.com/Keats/validator but at first glance it doesn't seem to meet our needs.Not sure yet whether we have a strong need for this fix but I can envision a time when we do.