The Crystal Programming Language Forum

Deserialize (from_yaml) based on a property's value

Howdy!

I know the (de)serialization story is a constant work in progress, and I really like the move to include YAML::Serializable over YAML.mapping but I’m not sure if I can currently do the following…

I want to be able to deserialize into a class based on a YAML field value.

For example:

...
  name: "Some name"
  type: foo
  value: "Some value"

I would like to be able to provide logic - probably a switch statement - to serialize into a specific type (all likely a child of a shared parent class) based upon this value.

Is this something that’s currently possible? I tried very briefly looking at other #from_yaml implementations but while trying to get my head around how it works (and the not-so-great compiler messages that get thrown in these scenarios), I wanted to make sure I was barking up the right tree to begin with.

Thanks a lot!

https://play.crystal-lang.org/#/r/7s08

It’s a bit ugly because I had to do that macro stuff in new because when you include YAML::Serializable it will define a self.new but it will also defined an inherited hook to define a self.new in subclasses that call super, and to avoid ending up in an infinite recursion for the case of a type not being Entity itself we call previous_def, which is the regular de-serialization.

It’s definitely something to improve.

Another alternative would be to avoid using a hierarchy of types, but Object.from_yaml requires returning the same type, which is really annoying, so we should remove that return type for more flexibility.

Great stuff, thanks for this.

Is this currently the pattern for more complex validation upon deserialization? Eg. validating a field’s values and other steps?

You could use https://github.com/Blacksmoke16/assert then add

def after_initialize
  validate!
end

which would run validations after the object is deserialized, raising an exception if it’s not valid.

Currently we can trade reimplementing from_yaml for the inheritance: https://play.crystal-lang.org/#/r/7syn