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
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
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>
Top comments (0)