4

我有一个控制器返回一个 json 结构,如下所示:

def show
  # .......
  o_json = deep_object_1_to_json(o)
  render :json => o_json
end

private
def deep_object_1_to_json(o)
  o.to_json(
    :include => {....})
end

现在我需要扩展它以返回 2 个对象。然而,显而易见的解决方案给我带来了问题:

def show
  # .......
  o1_json = deep_object_1_to_json(o)
  o2_json = deep_object_2_to_json(o)
  render :json => 
  {
         :object_1 => o1_json,
         :object_2 => o2_json
  }
end

这将返回一个带有 2 个转义 json 数据字符串的 json 对象!

deep_object_2_to_json 函数已经有多层嵌套包含,所以我宁愿不必将它们重构为单个函数。有没有办法使它易于扩展以在将来添加更多对象而不会出现上述双重转义问题?

感谢您的任何指示。

4

3 回答 3

7

听起来您应该构建一些to_json可以轻松调用的东西。

活动记录对象的明显候选对象是as_json. 除了将对象实际转换为 json 之外,这会执行所有to_json操作(包括:include选项等)。相反,您会得到一个 ruby​​ 哈希,您可以根据需要对其进行操作,然后调用 to_json。例如你可以做

render :json => {
  :o1 => object1.as_json(:include => :blah),
  :o2 => object2.as_json(:include => :blah)
}
于 2012-06-26T16:24:25.947 回答
1

如果您可以重构您的类以通过该方法返回它的 JSON to_json,您可以简单地将两个或多个对象放入一个数组并调用to_json该数组:

1.9.3-p125 :001 > require 'json'
 => true 
1.9.3-p125 :002 > [{foo: "bar"}, {bar: "foo"}].to_json
 => "[{\"foo\":\"bar\"},{\"bar\":\"foo\"}]" 

例子:

def to_json
  super(include: [:some_association])
end
于 2012-06-26T15:57:33.977 回答
1

您的控制器不应该将对象序列化为 JSON,直到它交付它进行渲染之前。

换句话说deep_object_1_to_json应该只是deep_object_1。然后,您可以将两个返回值打包到一个数组或散列中,并将其呈现为 JSON。

def show
  # .......
  o1 = deep_object_1(o)
  o2 = deep_object_2(o)
  render :json =>
  {
         :object_1 => o1,
         :object_2 => o2
  }
end

现在改变它可能会很痛苦,但为了你系统的未来,你真的应该这样做。JSON 只是一种通过网络或磁盘发送对象的格式;您的任何代码都不应该有任何对 JSON 的引用,除非它正在传递它以进行渲染。

于 2012-06-26T16:08:05.967 回答