Understanding Serde
joshmcguigan.com
joshmcguigan.com
Or now that I think of it, Template Haskell.
Not to mention how many languages are written in it: Elm, Purescript, Idris, GHC itself.
i guess today it only matter how many stars you repo has in github...
For JSON deserialisation, Serde is a very convenient API to use an existing JSON parser that someone else has (hand) written.
If you needed a new syntax, you'd have to write a new parser. I often implement communications protocols as part of my work. In most cases, Serde doesn't help me much there - I have to parse the protocol myself (e.g. using Nom).
Typically, although this depends on the specific encoding, a parser is required as one of the first stages of a deserialiser; normally a parser refers to something which applies the rules of something as least as complex as a CFG, as opposed to a lexer/scanner which typically just applies regular expressions; a combination of the two allows the serialised format to be interpreted.
You can show quite easily that JSON (and indeed any CFL) cannot be "parsed" using a lexer alone.
I had the vague notion that parsing was for human readable content and deserialization was for computer-to-computer content.
Now I tentatively make the distinction that compiling transforms streams into code (stream -> lex -> parse -> magic -> code) whereas deserialization is for data. Making parsing just one of the transformation steps for both compilation and deserialization.
I have no idea if serde follows this design, or if it has just hijacked the terms.
This way, you can write a serialize(foo) function which will work for any type, without needing any derives or marking the type as Serializable like in Java.
The closest equivalent to derive in D would be a mixin. You could declare a mixin which autogenerates the toJSON() fromJSON() methods based on the fields of a struct.
https://raphlinus.github.io/rust/2019/08/21/rust-bloat.html#...
That said, I've always had a slight problem with this approach to serialisation in general, which is that it makes it very hard to have multiple serialisation approaches for a single type (e.g. I want one casing rule for one target, and a different one for another). This seems effectively impossible with an approach based on annotations/macros. Would love to know how others have dealt with that.
Hmm, this is interesting, and something I hadn't thought of before. I'd probably try to solve it with a combination of the newtype pattern (create wrapper types for `MyThing`, like `MyThingJson` and `MyThingToml`) and the Serde flatten attribute. Then you could, for example, add `#[serde(rename_all = "lowercase")]` to the `MyThingJson` struct and `#[serde(rename_all = "snake_case")]` to the `MyThingToml` struct.
I haven't tested this though, so I'm not sure if the `rename_all` would flow through the flatten attribute as expected. Worst case you could duplicate the struct (or more likely, find or build a macro to do it for you) rather than use the newtype/flatten technique.
And at least in Java-land is much cleaner than stacking lots and lots of annotations on the same struct.
... Sorry, just trying to be funny.
This was where I first saw it as well. Years ago...