将嵌套结构转换为JSON

时间:2017-04-03 10:26:34

标签: json ruby

我找到了相反的答案,但没有找到嵌套结构到JSON的方式

假设我有这个红宝石结构

Attributes = Struct.new :name, :preferredLanguage, :telephoneNumber, :timeZone
User = Struct.new :email, :service, :preferredLanguage, :attributes

我为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\\\">\"" 

所以它运作良好,除非我使用gem Oj,我无法删除对象的名称并获得与to_h.to_json方法相同的

但是当我使用像用户

这样的嵌套Struct时会出现问题
user = User.new "Pedro@email.com", "coolService", "es", attributes
 # => #<struct User email="Pedro@email.com", service="coolService", preferredLanguage="es", attributes=#<struct Attributes name="Pedro", preferredLanguage="es", telephoneNumber="5555555", timeZone="Madrid">> 
user.to_h.to_json
 # => "{\"email\":\"Pedro@email.com\",\"service\":\"coolService\",\"preferredLanguage\":\"es\",\"attributes\":\"#<struct Attributes name=\\\"Pedro\\\", preferredLanguage=\\\"es\\\", telephoneNumber=\\\"5555555\\\", timeZone=\\\"Madrid\\\">\"}" 
Oj.dump user, mode: :compat
 # => "\"#<struct User email=\\\"Pedro@email.com\\\", service=\\\"coolService\\\", preferredLanguage=\\\"es\\\", attributes=#<struct Attributes name=\\\"Pedro\\\", preferredLanguage=\\\"es\\\", telephoneNumber=\\\"5555555\\\", timeZone=\\\"Madrid\\\">>\""

使用to_h.to_json我得到属性对象的字符串,而使用oj,这不是有效的JSON。而且我还有另一个问题,有任何来自java的GSON,jackson库在ruby中以相同的方式工作

1 个答案:

答案 0 :(得分:1)

如果你使用ActiveSupport(Rails),你可以开箱即用。当你似乎使用准系统Ruby时,只需递归地执行:

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\":\"Pedro@email.com\",\"service\":\"coolService\",\"preferredLanguage\":\"es\",\"attributes\":{\"name\":\"Pedro\",\"preferredLanguage\":\"es\",\"telephoneNumber\":\"5555555\",\"timeZone\":\"Madrid\"}}"

至于GSON,似乎有a wrapper for Ruby,但我不认为它被广泛使用。 Rails的猴子修补行为足以满足99.99%的可能用途。如果要更改自定义序列化,还可以定义自定义序列化程序。