0

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

我有这个作为序列化程序:

class AreaSerializer
  include FastJsonapi::ObjectSerializer
  attributes :id, :name, :cost_center, :notes
  has_many :children
end

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

  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": ""
    }
}]

}

这个想法是嵌套关系显示细节等。

4

3 回答 3

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
于 2020-03-08T15:07:35.823 回答
0

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

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

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

于 2021-03-31T04:24:51.620 回答
0

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

fast_jsonapi遵守JSON:API 规范,您可以在此处查看。

因此,您将无法使用关系辅助函数 (: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关系,但假设 anArea有很多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
于 2020-03-08T10:23:25.993 回答