如何使用Active Model ArraySerializer返回json“object”而不是json“array”?

时间:2016-01-21 20:02:53

标签: ruby-on-rails json active-model-serializers

使用Active Model Serializer,是否有一种简单而集成的方法可以在序列化集合时返回JSON“对象”(然后由客户端框架在javascript对象中转换)而不是JSON“数组”? (我引用了对象和数组,因为返回的JSON本质上是一个字符串)。

假设我有以下ArticleSerializer:

class ArticleSerializer < ActiveModel::Serializer
  attributes :id, :body, :posted_at, :status, :teaser, :title
end

我从ArticlesController调用它:

class ArticlesController < ApplicationController
  def index
    @feed = Feed.new(articles: Article.all)
    render json: @feed.articles, each_serializer: ArticleSerializer
  end
end

有没有办法将选项传递给序列化程序,使其返回如下内容:

{"articles":
  {
    "1":{ 
      ...
    },
    "2":{
      ...
    }
  }
}

而不是

{"articles":
  [
    { 
      "id":"1",
      ...
    },
    {
      "id":"2"
      ...
    }
  ]
}

编辑:我想这篇文章中提出的方法(继承AMS ArraySerializer)可能会有所帮助(Active Model Serializer and Custom JSON Structure

2 个答案:

答案 0 :(得分:3)

您必须编写适合您格式的自定义适配器。 或者,您可以在将哈希值传递给render之前修改哈希值。 如果你不介意迭代生成的哈希,你可以这样做:

ams_hash = ActiveModel::SerializableResource.new(@articles)
                                            .serializable_hash
result_hash = ams_hash['articles'].map { |article| { article['id'] => article.except(:id) } }
                                  .reduce({}, :merge)

或者,如果您希望这是默认行为,我建议切换到Attributes适配器(与Json适配器完全相同,除了没有文档根),并覆盖serializable_hash方法,如下所示:

 def format_resource(res)
   { res['id'] => res.except(:id) }
 end

 def serializable_hash(*args)
   hash = super(*args)
   if hash.is_a?(Array)
     hash.map(&:format_resource).reduce({}, :merge)
   else
     format_resource(hash)
   end
 end

答案 1 :(得分:0)

不,从语义上讲,您将返回一组文章。哈希只是Javascript中的对象,所以你基本上想要一个带有1..n方法的对象,它返回每篇文章,但这没有多大意义。