2016-01-21 68 views
2

使用Active Model Serializer,是否有一種簡單且集成的方式來在序列化集合時返回JSON「對象」(然後在客戶端框架中將其轉換爲JavaScript對象)而不是JSON「數組」? (我引用對象和數組,因爲返回的JSON本質上是一個字符串)。如何使用Active Model ArraySerializer返回json「object」而不是json「array」?

比方說,我有以下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

回答

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 
+0

你說得對。看看源代碼,看起來沒有這樣的選項。我想我必須修改json_api適配器[link](https://github.com/rails-api/active_model_serializers/blob/master/lib/active_model/serializer/adapter/json_api.rb)中的serializable_hash_for_collection方法。或者修改散列,使用RegEx獲得最佳性能。或者迭代我的文章集合,並在每個文檔上調用單個項目序列化器,並在將它們傳遞給呈現之前將它們包裝在散列中。非常感謝!!! – Cedric

+0

@Cedric看看我剛剛勾畫的解決方案! – beauby

+0

這看起來非常好。我明天會試一試,如果有作品會讓你知道,但它看起來非常好。 Merci beaucoup! – Cedric

0

不,語義你退稿的數組。哈希只是Javascript中的對象,所以你基本上需要一個帶有1..n方法的對象來返回每篇文章,但這沒有多大意義。

+0

感謝。這可能沒有道理,但這正是我在js框架中用normalizrjs強制執行的操作......這種將數組類結構存儲爲平面對象的模式是平面數據庫存儲數據的方式。我可以編寫一個手工序列化器來遍歷我的每篇文章,獲取它們的ID,將它們單獨傳遞給AMS序列化器,然後在將它們傳回控制器之前構建一個JSON平面對象/散列表,然後將其渲染爲JSON。但性能方面......目的是爲了緩解前端。我可能會嘗試使用REGEX。 – Cedric