Why this (evaluated in Rails console)
[{:a => :b}].collect {|x| OpenStruct.new(x)}.to_json
adds a \"table\" record in there?
With ruby 2.1.2 you can use the following to get JSON without the table root element:
[{:a => :b}].collect {|x| OpenStruct.new(x).to_h}.to_json
=> "[{\"a\":\"b\"}]"
I get around the problem by subclassing OpenStruct like so:
class DataStruct < OpenStruct
def as_json(*args)
super.as_json['table']
end
end
then you can easily convert to JSON like so:
o = DataStruct.new(a:1, b:DataStruct.new(c:3))
o.to_json
# => "{\"a\":1,\"b\":{\"c\":3}}"
Neat huh? So in answer to your question, you'd write this instead:
[{:a => :b}].collect {|x| DataStruct.new(x)}.to_json
giving you:
=> "[{\"a\":\"b\"}]"
openstruct_array.map(&:to_h).as_json
I found the other responses to be a tad confusing having landed here to just figure out how to turn my OpenStruct into a Hash
or JSON. To clarify, you can just call marshal_dump
on your 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\"}"
I personally would be hesitant to monkey-patch OpenStruct
unless you're doing it on a subclass, as it may have unintended consequences.
Because @table is a instance variable of OpenStruct and Object#as_json returns Hash of instance variables.
In my project, I implemented OpenStruct#as_json to override the behaviour.
require "ostruct"
class OpenStruct
def as_json(options = nil)
@table.as_json(options)
end
end
Use marshal_dump
, although this somewhat defeats the purpose of converting it to an OpenStruct beforehand:
[{:a => :b}].collect {|x| OpenStruct.new(x).marshal_dump }.to_json
=> "[{\"a\":\"b\"}]"
The shorter way would be:
[{:a => :b}].to_json
"[{\"a\":\"b\"}]"
Alternatively you could moneky patch OpenStruct#as_json
as shown in hiroshi's answer:
require "ostruct"
class OpenStruct
def as_json(options = nil)
@table.as_json(options)
end
end