Implement to_json in dry-struct

Hi,

I’d like to suggest implementing the to_json method in dry-structs.

The basis of my argument is what would I expect as a novice user?
Here is an example:

class User < Dry::Struct
  attribute :name, Types::String.optional
   attribute :age, Types::Coercible::Integer
end

user = User.new({name: 'test', age: 3})
JSON.generate(user) # produces =>  "\"#<User:0x00005575205a1550>\""

This behavior was unexpected for me! In hindsight it is fairly obvious to me why it doesn’t work (because to_json isn’t implemented). And with a lot of tedious debugging I finally worked out what was going on (the default Object.to_json method is literally def to_json(*) to_s.to_json end.

However, learning all this took hours of time and a level of knowledge about JSON generation I’ve never needed before. I’ve been spoilt by rails where all the hard work has already been done!

I’ve gone ahead and derived my own struct base class which implements to_json, which I am now using:

  class SerializableStruct < Dry::Struct
    # Allows a struct to be serialized into JSON by first converting it to a hash
    def to_json(*a)
      to_h.to_json(*a)
    end
  end

May I suggest adding a default to_json method to dry-struct?
If not, a warning about a lack of default implementation of to_json in the documentation would go a long way to saving a lot of time for people like me.

Quite frankly, I believe it’s on rails. Serializing to JSON is not a concern of dry-struct, there is no “right” way to do it automatically as I can see (speaking from experience). What you ended up is how it’s supposed to be done in my view. However, if we had a plugin system of a kind we could have a JSON serialization plugin. With an interface like class MyStruct < Dry::Struct; use :to_json; end

I think, I disagree, that it is ‘on rails’.

Rails does implement some helpers for JSON serialization, through ActiveSupport::JSON. The patch to Object even is pretty helpful in this case because it calls to_hash and things Just Work™.

However, my current project isn’t using Rails. What then? Do I add
ActiveSupport as a dependency? I’d prefer not to.

IMHO it’s really the design of JSON that’s the problem. It requires you to mess up your class with a separate concern to make it serializable. I’m not fond of this but JSON is part of the Ruby stdlib so I think it is a behaviour we’re stuck with.

While Rails can be overly helpful, it matches the experience I’d expect (given my familiarity of producing JSON from C# and JavaScript).

A plugin would be perfectly fine too, especially given a documentation example :slightly_smiling_face: