Reputation: 11532
I find the answer for the reverse but not for the way nested struct to JSON
Suppose that I have this ruby structs
Attributes = Struct.new :name, :preferredLanguage, :telephoneNumber, :timeZone
User = Struct.new :email, :service, :preferredLanguage, :attributes
I create the struct for Attributes
attributes = Attributes.new "Pedro", "es", "5555555", "Madrid"
# => #<struct Attributes name="Pedro", preferredLanguage="es", telephoneNumber="5555555", timeZone="Madrid">
attributes.to_h.to_json
# => "{\"name\":\"Pedro\",\"preferredLanguage\":\"es\",\"telephoneNumber\":\"5555555\",\"timeZone\":\"Madrid\"}"
Oj.dump attributes
# => "{\"^u\":[\"Attributes\",\"Pedro\",\"es\",\"5555555\",\"Madrid\"]}"
Oj.dump attributes, mode: :compat
# => "\"#<struct Attributes name=\\\"Pedro\\\", preferredLanguage=\\\"es\\\", telephoneNumber=\\\"5555555\\\", timeZone=\\\"Madrid\\\">\""
So it works well, except when I use the gem Oj
, that I cannot remove the name of the object and get the same as with the to_h.to_json
methods
But the problem comes when I use a nested Struct like User
user = User.new "[email protected]", "coolService", "es", attributes
# => #<struct User email="[email protected]", service="coolService", preferredLanguage="es", attributes=#<struct Attributes name="Pedro", preferredLanguage="es", telephoneNumber="5555555", timeZone="Madrid">>
user.to_h.to_json
# => "{\"email\":\"[email protected]\",\"service\":\"coolService\",\"preferredLanguage\":\"es\",\"attributes\":\"#<struct Attributes name=\\\"Pedro\\\", preferredLanguage=\\\"es\\\", telephoneNumber=\\\"5555555\\\", timeZone=\\\"Madrid\\\">\"}"
Oj.dump user, mode: :compat
# => "\"#<struct User email=\\\"[email protected]\\\", service=\\\"coolService\\\", preferredLanguage=\\\"es\\\", attributes=#<struct Attributes name=\\\"Pedro\\\", preferredLanguage=\\\"es\\\", telephoneNumber=\\\"5555555\\\", timeZone=\\\"Madrid\\\">>\""
With the to_h.to_json
I get the string of the attributes object, And with the oj, this is not a valid JSON. and also I have another question, there is any GSON, jackson library from java that works the same way in ruby
Upvotes: 0
Views: 836
Reputation: 36110
If you were to use ActiveSupport (Rails), you would get this out of the box. As you seem to be using barebones Ruby, just do it recursively:
hashify = lambda do |struct|
as_hash = struct.to_h
struct_keys = as_hash.select { |_, v| v.is_a? Struct }.map(&:first)
struct_keys.each { |key| as_hash[key] = hashify.(as_hash[key]) }
as_hash
end
hashify.(user).to_json
# => "{\"email\":\"[email protected]\",\"service\":\"coolService\",\"preferredLanguage\":\"es\",\"attributes\":{\"name\":\"Pedro\",\"preferredLanguage\":\"es\",\"telephoneNumber\":\"5555555\",\"timeZone\":\"Madrid\"}}"
As for GSON, there seems to be a wrapper for Ruby, but I don't think it's that widely used. Rails' monkey patched behaviour is good enough for 99.99% of possible uses. It also lets you define your custom serializers if you want to change it.
Upvotes: 1