将哈希收集到OpenStruct中会创建"表"条目

lza*_*zap 13 ruby ruby-on-rails

为什么这样(在Rails控制台中评估)

[{:a => :b}].collect {|x| OpenStruct.new(x)}.to_json
Run Code Online (Sandbox Code Playgroud)

在那里添加"表"记录?

"[{\"table\":{\"a\":\"b\"}}]
Run Code Online (Sandbox Code Playgroud)

我想要这个:

"[{\"a\":\"b\"}]
Run Code Online (Sandbox Code Playgroud)

这是否意味着Rails的to_json方法以不同的方式处理OpenStruct?当我在irb中尝试它时,它不在那里:

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

hir*_*shi 26

因为@table是OpenStruct的实例变量Object#as_json返回实例变量的Hash.

在我的项目中,我实现了OpenStruct#as_json来覆盖行为.

require "ostruct"
class OpenStruct
  def as_json(options = nil)
    @table.as_json(options)
  end
end
Run Code Online (Sandbox Code Playgroud)


Mat*_*att 15

使用marshal_dump,虽然这有点违背了事先将其转换为OpenStruct的目的:

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

更短的方式是:

[{:a => :b}].to_json
"[{\"a\":\"b\"}]"
Run Code Online (Sandbox Code Playgroud)

或者你可以根据OpenStruct#as_jsonhiroshi的回答显示moneky补丁:

require "ostruct"
class OpenStruct
  def as_json(options = nil)
    @table.as_json(options)
  end
end
Run Code Online (Sandbox Code Playgroud)


Kev*_*son 9

我通过子类化OpenStruct来解决这个问题:

class DataStruct < OpenStruct
  def as_json(*args)
    super.as_json['table']
  end
end
Run Code Online (Sandbox Code Playgroud)

然后您可以轻松转换为JSON,如下所示:

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

整洁吧?所以在回答你的问题时,你会写下这个:

[{:a => :b}].collect {|x| DataStruct.new(x)}.to_json
Run Code Online (Sandbox Code Playgroud)

给你:

=> "[{\"a\":\"b\"}]"
Run Code Online (Sandbox Code Playgroud)


ste*_*son 7

我发现其他回复有点令人困惑,因为我来到这里只是为了弄清楚如何将我的 OpenStruct 转换为 aHash或 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\"}"
Run Code Online (Sandbox Code Playgroud)

我个人会对猴子补丁犹豫不决,OpenStruct除非你在子类上这样做,因为它可能会产生意想不到的后果。