Should Json::Serializable provide a method to emit a Json::Any?

I think it’s important to understand that these two concepts are not interchangeable. JSON::Serializable is a way to (de)serialize a known structure to/from json. While JSON::Any allows processing dynamic JSON. They each have their own uses. I.e. it’s not likely that one will be removed in favor of another.

This makes sense given PG doesn’t know what data you’ll be putting into it. I think there is room for some sort of abstraction to make working with structured data easier. E.x. having some functionality/allowing functionality to be added to allow for like “hey this type is_a? JSON::Serialiazble and this column is a json column, i can just use to/from_json instead given the structure is static/known.”

For example Granite allows doing stuff like this: column my_type : MyType?, column_type: "JSON", converter: Granite::Converters::Json(MyType, JSON::Any). Which tells it that it should use the Json converter to go to/from the database. Which just wraps the to/from_json methods. granite/src/granite/converters.cr at master · amberframework/granite · GitHub

EDIT: Of course It would be more ideal if this concept was baked into the DB abstractions. I.e. so that the data is (de)serialized directly versus needing to do the slightly hacky value.to_json since the DB driver deserializes it into a JSON::Any first if the column was set to JSON::Any.

I would be strongly against adding those methods automatically. It would be pretty trivial to add a def self.new(json : JSON::Any) : self overload if you really needed it. However, given you’re working with known types JSON::Any has little use.

3 Likes