DEV Community

loading...

Transparently serialize and deserialize ValueObjects to JSON

Piotr Romańczuk
Updated on ・1 min read

This is the way I choose when I want to serialize and deserialize ValueObjects transparently to JSON in Rails app

Put serialization methods into module

module ValueObjectJsonSerialization
  def to_json(*args)
    #override AtiveSupport to_json extensions if active
    args = JSON::SAFE_STATE_PROTOTYPE.dup if args == []
    {
      :json_class => self.class.to_s,
    }.merge(as_json).to_json(*args)
  end

  def as_json(_=nil)
    # unused argument to satisfy ActiveSupport as_json signature
    { :json_class => self.class.to_s }.merge(_as_json)
  end
end

Enter fullscreen mode Exit fullscreen mode

Use them in your ValueObject class and make it transparently serializable

class PublicationDate
  include ValueObjectJsonSerialization
  def initialize(y, m=nil, d=nil)
    @y, @m, @d = y, m, d 
  end

  def self.json_create(h)
    new(h['y'], h['m'], h['d'])
  end

  def _as_json
    { y: @y, m: @m, d: @d }.compact
  end
end
Enter fullscreen mode Exit fullscreen mode

DEMO

require 'json'
[9] pry(main)> PublicationDate.new(2021, 4)
=> #<PublicationDate:0x00005652cd6a5c40 @d=nil, @m=4, @y=2021>
[10] pry(main)> PublicationDate.new(2021, 4, 19).to_json
=> "{\"json_class\":\"PublicationDate\",\"y\":2021,\"m\":4,\"d\":19}
[11] pry(main)> JSON.load PublicationDate.new(2021, 4, 19).to_json
=> #<PublicationDate:0x00005652cd717d18 @d=19, @m=4, @y=2021>
Enter fullscreen mode Exit fullscreen mode

Discussion (0)