ChanServ changed the topic of #crystal-lang to: The Crystal programming language | | Fund Crystal's development: | GH: | Docs: | Gitter:
ur5us has quit [Ping timeout: 252 seconds]
avane has quit [Ping timeout: 252 seconds]
avane_ has joined #crystal-lang
avane_ has quit [Client Quit]
avane has joined #crystal-lang
ur5us has joined #crystal-lang
ur5us has quit [Ping timeout: 240 seconds]
ur5us has joined #crystal-lang
<FromGitter> <> hightower2: done!
<FromGitter> <> I've implemented custom serialization/deserialization in Crystalizer
<FromGitter> <> I don't really know how @Blacksmoke16 has came up with something more complicated with 😅 ⏎ Or maybe that's just me because not my code
ur5us has quit [Ping timeout: 250 seconds]
<FromGitter> <Blacksmoke16> the key difference i think is it works *after* it already deserialized the data, so you can work with JSON::Any for example and be able to easily check the data for given values and such
<FromGitter> <Blacksmoke16> versus trying to do all that while deserializing it
<FromGitter> <> without creating a custom type?
<FromGitter> <Blacksmoke16> for custom classes and stuff you need to include a module
<FromGitter> <> I see, for me data validation and deserialization can be separated
<FromGitter> <Blacksmoke16> that is part for allowing it to pick the right overload, and part defines a method that describes the properties that should be (de)serialized. I.e. based on the applied annotations
<FromGitter> <Blacksmoke16> they are
<FromGitter> <Blacksmoke16> are separate components so are separate modules
<FromGitter> <> Right, there are in a different library
<FromGitter> <Blacksmoke16> yup
<FromGitter> <Blacksmoke16> so can be used independently of the other, but shows how they can be used together
<FromGitter> <Blacksmoke16> did some refactoring in Athena land so you can just do like: ⏎ ⏎ ```code paste, see link``` ⏎ ⏎ now. I.e. it knows what type to deserialize based on the type restriction of the related argument []
<FromGitter> <> And then you said "versus trying to do all that while deserializing it". But we can use my lib to deserialize, then yours to validate
<FromGitter> <Blacksmoke16> yea
<FromGitter> <Blacksmoke16> but more so meant how JSON::Serializable does it all with a PullParser, so doing stuff like discriminator is harder because you might not have deserialized that property yet
<FromGitter> <Blacksmoke16> nor is it really possible to tap into if you wanted to allow dynamic skipping of a property for example
<FromGitter> <> For discriminator, or having custom strategies like a `size` field setting the size of the next field (e.g. a string), how I see the whole thing is to have a custom type handling this, instead of supporting it natively
<FromGitter> <Blacksmoke16> for sure, having a DTO to represent that would be a much better option
<FromGitter> <Blacksmoke16> although it could be done with a :P
<FromGitter> <> I don't understand what's a DTO and the VirtualProperty :/
<FromGitter> <Blacksmoke16> `data transfer object`, basically can think of it as a type that is meant to be used to transfer data between systems w/o containing any business logic
<FromGitter> <Blacksmoke16> because the structure of that data is part of your API so for larger applications can make sense to decouple that from your database models for example
<FromGitter> <Blacksmoke16> virtual property just allows the return value of a method to be included in the serialized data, which could be used for dynamic data. e.g. `def count; @data.size; end`
<FromGitter> <> I see!
<FromGitter> <Blacksmoke16> 👍
<FromGitter> <> why Virtual Property? If I emplement that, I likely juste reuse the `@[Crystalizer::Field]` annotation haha 😄
<FromGitter> <Blacksmoke16> i guess in my case i dont have a `Field` annotation so needed something
<FromGitter> <> I'm easily lost with all this annotations I admit
<FromGitter> <Blacksmoke16> that's what the docs are for :P
<FromGitter> <Blacksmoke16> was better than having 1 annotation with a lot of fields, at least that was my thinking when first making it
<FromGitter> <> for DTO, a dedicated custom type can be used, implemented a serialize and deserialize, no?
<FromGitter> <Blacksmoke16> pretty much yea, can think of it as a serializable record. I.e. only getters
<FromGitter> <Blacksmoke16> makes sense for larger APIs, prob not really needed if you only have a few endpoints
<FromGitter> <> I had this with my previous test game, the messages were object with just data fields
<FromGitter> <Blacksmoke16> exactly! then you're free to change the internal data model w/o breaking communication between systems
<FromGitter> <> In fact, it was the simplest approach I had in mind - what was the alternatives?
<FromGitter> <> Adding logic on the server (Crystal) side in the class messages?
<FromGitter> <> Looking at the visitors, "dynamic" YAML and JSON parsing (to Any) are used (?!).
<FromGitter> <Blacksmoke16> hm?
<FromGitter> <Blacksmoke16> it's mainly more helpful in a like REST API context in that a REST resource does not need to mean a database table
<FromGitter> <Blacksmoke16> but if you tightly couple the endpoint response to how a table is structured it could be an issue if you change something about that internal representation as the payload would also change
<FromGitter> <Blacksmoke16> yea, that's what i mean you're working with the already deserialized data
<FromGitter> <Blacksmoke16> not as performant compared to YAML::Serializable, but still plenty fast and a lot more flexible
<FromGitter> <> Could have both, supporting static and dynamic
<FromGitter> <Blacksmoke16> although tbh im not super happy with the implementation, might try and refactor it one of these days
<FromGitter> <Blacksmoke16> possibly yea
<FromGitter> <> I guess Crystalizer won't have all the advanced features you seek
<FromGitter> <Blacksmoke16> other main thing i wanted was to have the serializer be its own obj. just fits better into rest of athena that way, and makes unit testing a bit easier
<FromGitter> <Blacksmoke16> so yea, are just two diff implementations with diff goals
<FromGitter> <> I've changed this recently
<FromGitter> <> Now there is a Deserializer, Serializer and Format interfaces
<FromGitter> <> It is a lot better to accept a given type to implement custom serialization of course
olbat has joined #crystal-lang
f1refly has quit [Ping timeout: 248 seconds]
f1refly has joined #crystal-lang
olbat[m] has joined #crystal-lang
olbat[m] is now known as Guest1640
Guest1640 has quit [Client Quit]
Guest1640 has joined #crystal-lang
Guest1640 is now known as olbat-m
hightower2 has joined #crystal-lang
ur5us has joined #crystal-lang
ur5us has quit [Remote host closed the connection]
ur5us has joined #crystal-lang
Starfoxxes has quit [Ping timeout: 240 seconds]
Starfoxxes has joined #crystal-lang
ur5us has quit [Remote host closed the connection]
ur5us has joined #crystal-lang
notzmv has quit [Read error: Connection reset by peer]
notzmv has joined #crystal-lang