Rails序列化-fast_jsonapi / active_model_serializers

时间:2019-12-24 21:19:26

标签: ruby-on-rails json serialization fastjsonapi

我迷上了fast_jsonapi / active_model_serializers来构建API。我掌握了基础知识,但似乎停留在自定义解决方案上。

我有这个作为序列化器:

类AreaSerializer   包括FastJsonapi :: ObjectSerializer   属性:id,:name,:cost_center,:notes   has_many:儿童 结束

在我的区域模型中,我有:

  has_many :children, -> { Area.where(ancestry: id) }

我的控制器如下:

class Api::V1::AreasController < ApiController

  def index
    render json: AreaSerializer.new(Area.root).serialized_json
  end

end

区域与祖先的宝石嵌套在层次结构中。输出为:

{"data":[{"id":"1","type":"area","attributes":{"id":1,"name":"Calgary","cost_center":"123456","notes":""},"relationships":{"children":{"data":[{"id":"3","type":"child"}]}}},{"id":"2","type":"area","attributes":{"id":2,"name":"Edmonton","cost_center":"78946","notes":""},"relationships":{"children":{"data":[]}}}]}

我正在寻找这样的出场机会:

{"data":[{"id":"1","type":"area","attributes":{"id":1,"name":"Calgary","cost_center":"123456","notes":""},"relationships":{"areas":{"data":[{"id":"3","type":"area","attributes":{"id":3,"name":"Child Area","cost_center":"123456","notes":""}}]}}},{"id":"2","type":"area","attributes":{"id":2,"name":"Edmonton","cost_center":"78946","notes":""}}]}

这个想法就是嵌套关系显示细节的地方。

3 个答案:

答案 0 :(得分:0)

我刚刚开始在Rails项目中使用fast_jsonapi

fast_jsonapi遵守JSON:API spec which you can see here.

因此,您将无法使用关系帮助器函数(:has_many,:belongs_to)实现所需的输出,该输出将relationships键内的区域属性嵌套。

"relationships": {
        "areas": {
            "data": [{
                "id": "3",
                "type": "area",
                "attributes": { // nesting attributes of area
                    "id": 3,
                    "name": "Child Area",
                    "cost_center": "123456",
                    "notes": ""
                }
            }]
        }
    }

JSON:API指定:

为了减少HTTP请求的数量,服务器可以允许响应 包括相关资源以及请求的主要资源 资源。这样的响应称为“复合文档”。

因此,您将在名为area的键中拥有included的属性。

为了获得响应中的included键,您需要在控制器中为序列化程序提供一个options哈希。

我不太了解您的模型Area的关系,但是假设Area有很多SubArea

class Api::V1::AreasController < ApiController

  def index
    // serializer options
    options = {
      include: [:sub_area],
      collection: true
    }
    render json: AreaSerializer.new(Area.root, options).serialized_json
  end

end

答案 1 :(得分:0)

您不能在fast_jsonapi中使用关联。以嵌套格式获取响应。您需要添加方法并需要创建另一个序列化器。

class AreaSerializer
  include FastJsonapi::ObjectSerializer

  set_type 'Area'

  attributes :id, :name, :cost_center, :notes

 attribute :childrens do |area, params|
     ChildrenSerializer.new(area.childrens, {params: 
     params})
  end
end

class ChildrenSerilizer
   include FastJsonapi::ObjectSerializer
    set_type 'Area'
    attributes :id, :name ... 
end

答案 2 :(得分:0)

我开始使用上面列出的技术,但最终分叉并重新编写了 jsonapi-serializer gem,因此它允许嵌套(最多 4 层深)并消除了 relationships 和 {{ 1}} 键。我也很沮丧它只输出 ID 和 TYPE 键,其中 TYPE 大多数时候是多余的,因为对象通常在数组中保持相同的类作为示例,人们很少使用真正的多态性(尽管它仍然支持这个并输出 ID /type 用于多态关系)。

我重写的最好部分可能是它允许通过新的 attributes 输入在 json 密钥树中的任何位置进行确定性字段选择。

https://github.com/rubesMN/jsonapi-serializer