Сбор хэшей в OpenStruct создает запись "table"

Почему это (оценивается в консоли Rails)

[{:a => :b}].collect {|x| OpenStruct.new(x)}.to_json

добавляет запись "таблицы"?

"[{\"table\":{\"a\":\"b\"}}]

Я хочу только это:

"[{\"a\":\"b\"}]

Означает ли это, что метод Rails to_json обрабатывает OpenStruct по-другому? Когда я пробую его в irb, его там нет:

require 'ostruct'
[{:a => :b}].collect {|x| OpenStruct.new(x)}.inspect

Ответ 1

Используйте marshal_dump, хотя это несколько поражает цель его предварительного преобразования в OpenStruct:

[{:a => :b}].collect {|x| OpenStruct.new(x).marshal_dump }.to_json
=> "[{\"a\":\"b\"}]"

Более короткий путь:

[{:a => :b}].to_json
"[{\"a\":\"b\"}]"

В качестве альтернативы вы могли бы moneky patch OpenStruct#as_json, как показано в hiroshi ответе:

require "ostruct"
class OpenStruct
  def as_json(options = nil)
    @table.as_json(options)
  end
end

Ответ 3

Я обойду проблему, подклассифицируя OpenStruct следующим образом:

class DataStruct < OpenStruct
  def as_json(*args)
    super.as_json['table']
  end
end

то вы можете легко преобразовать в JSON так:

o = DataStruct.new(a:1, b:DataStruct.new(c:3))
o.to_json
# => "{\"a\":1,\"b\":{\"c\":3}}"

Аккуратно? Поэтому, отвечая на ваш вопрос, вы должны написать это вместо:

[{:a => :b}].collect {|x| DataStruct.new(x)}.to_json

дает вам:

=> "[{\"a\":\"b\"}]"

Ответ 4

С ruby ​​2.1.2 вы можете использовать следующее, чтобы получить JSON без корневого элемента таблицы:

[{:a => :b}].collect {|x| OpenStruct.new(x).to_h}.to_json
 => "[{\"a\":\"b\"}]"

Ответ 5

Я нашел, что другие ответы были немного запутанными, приземлившись здесь, чтобы просто выяснить, как превратить OpenStruct в Hash или JSON. Чтобы уточнить, вы можете просто называть marshal_dump на OpenStruct.

$ OpenStruct.new(hello: :world).to_json
=> "{\"table\":{\"hello\":\"world\"}}"

$ OpenStruct.new(hello: :world).marshal_dump
=> {:hello=>:world}

$ OpenStruct.new(hello: :world).marshal_dump.to_json
=> "{\"hello\":\"world\"}"

Я лично был бы неспособен к monkey-patch OpenStruct, если вы не делаете это в подклассе, так как это может иметь непреднамеренные последствия.

Ответ 6

openstruct_array.map(&:to_h).as_json