-
-
Notifications
You must be signed in to change notification settings - Fork 786
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Derived fields #1689
Comments
To me that doesn't look like a job for deserialization at all. Why should deserialization be concerned with compiling a regular expression? It's a massive breach of single responsibility. This problem can be solved by splitting the type in two: a "pure data" type, which is only concerned with serialization and deserialization of the minimal amount of information necessary to uniquely identify and compute the state of the whole thing, then an "object-like" or "live" type, which constructs itself from the pure data type and has the rich interface you need with potential optimizations, like pre-computed regexes, applied in the constructor (or at least only in this second type). |
That is fundamentally wrong. The responsibility of a serializer/deserializer is to convert from memory to wire format, not to cast judgment on which memory format is "ok" and and which isn't. How the function is called is of no relevance here, if it's Serde already allows all those steps on their own - there is
Field renaming also works already with So the only difference left is that this would populate two in memory fields from a single source field - which, in a way, also already exists with objects that are key/value pairs but is limited to this one specific case. So all of the components that would create a derive option are clearly the responsibility of the deserialiser - all derive would add is a convenient way to use them together so they don't excluding each other and prevent the deserialiser to do something that isn't it's reasonability - trying to dictate what my memory representation is. |
The deserializer doesn't dictate what your memory representation is — good practice and taste does. Furthermore, asserting that (i) just because something can be done it is desirable to do it and (b) an arbitrary combination of existing components/features of a framework must automatically be sensible is misguided. Lumping these parts together is of course (likely) possible, but it matters how they are used. In fact, in this case, it is exactly the decoupling between them that would get lost and that's what leads to the violation of responsibility boundaries. |
That makes absolutely no sense, they are usable together, again the only difference is that a single field on the wire will be deserialised into two fields in memory - there is absolutely nothing that violates responsibility boundaries. If you have an issue with regexp then use network addresses as an example where you might want to preserve the original string representation along side the numbers so user input like The same as DateTime would get serialized to a string and deserialized to a structure. |
I would prefer not to build anything dedicated to this into serde_derive. For the snippet at the top of this issue, I would recommend handling that kind of thing by writing the Deserialize impl for impl<'de> Deserialize<'de> for MyRe {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let src = MyReRepr::deserialize(deserializer)?;
let re = Re::compile(&src).map_err(...)?;
Ok(MyRe { src, re })
}
} |
Sometimes a struct contains computed fields that logically derive from another attribute of the struct. It would be nice to have a way to express this in serde.
Something like:
The text was updated successfully, but these errors were encountered: