我用Rails 4.2.1active_model_serializers 0.10.0.rc2

I'm new to API's and chose active_model_serializers because it seems to be becoming the standard for rails (Although I'm not opposed to using RABL or another serializer)

我遇到的问题是,我似乎不能在多级关系中包含各种属性.例如,我有:

Projects

class ProjectSerializer < ActiveModel::Serializer
  attributes                      :id, 
                                  :name,
                                  :updated_at

  has_many                        :estimates, include_nested_associations: true

end

and Estimates

class EstimateSerializer < ActiveModel::Serializer
  attributes                      :id, 
                                  :name, 
                                  :release_version, 
                                  :exchange_rate, 
                                  :updated_at,

                                  :project_id, 
                                  :project_code_id, 
                                  :tax_type_id 

  belongs_to                      :project
  belongs_to                      :project_code
  belongs_to                      :tax_type

  has_many                        :proposals

end

Proposals

class ProposalSerializer < ActiveModel::Serializer
  attributes                      :id, 
                                  :name, 
                                  :updated_at,

                                  :estimate_id

  belongs_to                      :estimate
end

当我打到/projects/1的时候,上面的会产生:

{
  "id": 1,
  "name": "123 Park Ave.",
  "updated_at": "2015-08-09T02:36:23.950Z",
  "estimates": [
    {
      "id": 1,
      "name": "E1",
      "release_version": "v1.0",
      "exchange_rate": "0.0",
      "updated_at": "2015-08-12T04:23:38.183Z",
      "project_id": 1,
      "project_code_id": 8,
      "tax_type_id": 1
    }
  ]
}

However, what I'd like it to produce is:

{
  "id": 1,
  "name": "123 Park Ave.",
  "updated_at": "2015-08-09T02:36:23.950Z",
  "estimates": [
    {
      "id": 1,
      "name": "E1",
      "release_version": "v1.0",
      "exchange_rate": "0.0",
      "updated_at": "2015-08-12T04:23:38.183Z",
      "project": { 
        "id": 1,
        "name": "123 Park Ave."
      },
      "project_code": {
        "id": 8,
        "valuation": 30
      },
      "tax_type": {
        "id": 1,
        "name": "no-tax"
      },
      "proposals": [
        {
          "id": 1,
          "name": "P1",
          "updated_at": "2015-08-12T04:23:38.183Z"
        },
        {
          "id": 2,
          "name": "P2",
          "updated_at": "2015-10-12T04:23:38.183Z"
        }
      ]
    }
  ]
}

Ideally, I'd also like to be able to specify which attributes, associations, and attributes of those associations are included in each serializer.

我一直在研究AMS的问题,对于如何处理这个问题(或者如果这种功能实际上得到了支持),似乎存在一些反复,但我很难弄清楚当前的状态到底是什么.

One of the proposed solutions was to override the attribute with a method to call the nested attributes, but that seems to be regarded as a hack so I wanted to avoid it if possible.

Anyway, an example of what of how to go about this or general API advice would be much appreciated.

推荐答案

So this my not be the best or even a good answer, but this is working how I need it to.

虽然在AMS中使用json_api适配器时似乎支持包含嵌套和侧加载属性,但我需要支持平面JSON.此外,此方法运行良好,因 for each 序列化程序都专门生成我需要的内容,独立于任何其他序列化程序,而无需在控制器中执行任何操作.

始终欢迎备注/替代方法.

Project Model

class Project < ActiveRecord::Base      
  has_many  :estimates, autosave: true, dependent: :destroy
end

ProjectsController

def index
  @projects = Project.all
  render json: @projects
end

ProjectSerializer

class ProjectSerializer < ActiveModel::Serializer
  attributes  :id, 
              :name,
              :updated_at,

              # has_many
              :estimates



  def estimates
    customized_estimates = []

    object.estimates.each do |estimate|
      # Assign object attributes (returns a hash)
      # ===========================================================
      custom_estimate = estimate.attributes


      # Custom nested and side-loaded attributes
      # ===========================================================
      # belongs_to
      custom_estimate[:project] = estimate.project.slice(:id, :name) # get only :id and :name for the project
      custom_estimate[:project_code] = estimate.project_code
      custom_estimate[:tax_type] = estimate.tax_type

      # has_many w/only specified attributes
      custom_estimate[:proposals] = estimate.proposals.collect{|proposal| proposal.slice(:id, :name, :updated_at)}

      # ===========================================================
      customized_estimates.push(custom_estimate)
    end

    return customized_estimates
  end
end

Result

[
  {
    "id": 1,
    "name": "123 Park Ave.",
    "updated_at": "2015-08-09T02:36:23.950Z",
    "estimates": [
      {
        "id": 1,
        "name": "E1",
        "release_version": "v1.0",
        "exchange_rate": "0.0",
        "created_at": "2015-08-12T04:23:38.183Z",
        "updated_at": "2015-08-12T04:23:38.183Z",
        "project": {
          "id": 1,
          "name": "123 Park Ave."
        },
        "project_code": {
          "id": 8,
          "valuation": 30,
          "created_at": "2015-08-09T18:02:42.079Z",
          "updated_at": "2015-08-09T18:02:42.079Z"
        },
        "tax_type": {
          "id": 1,
          "name": "No Tax",
          "created_at": "2015-08-09T18:02:42.079Z",
          "updated_at": "2015-08-09T18:02:42.079Z"
        },
        "proposals": [
          {
            "id": 1,
            "name": "P1",
            "updated_at": "2015-08-12T04:23:38.183Z"
          },
          {
            "id": 2,
            "name": "P2",
            "updated_at": "2015-10-12T04:23:38.183Z"
          }
        ]
      }
    ]
  }
]

I basically disregarded trying to implement any has_many or belongs_to associations in the serializers and just customized the behavior. I used slice to select specific attributes. Hopefully a more elegant solution will be forth coming.

Json相关问答推荐

按照对象键的值对PostgreSQL JSONB对象进行排序'

删除JSON文件的特定内容

如何使用GoFr返回XML响应?

组合不同属性的Jolt Spec

使用 JOLT 将日期格式转换为 JSON

如何对未知/变量键的字典进行编码?

如何 Select 一个值,这是可选的 - 使用 jq

将来自 Golang 的 JSON API 调用响应输出到 nextjs 前端

JOLT JSON 将值从一对多转换为一对一

在Flutter 中将 map 的 Json 转换为 list

jq搜索特定字符串并输出对应的父值

boost::json::value 的大括号初始化将其从对象转换为数组

N1QL 搜索对象内的某些对象

避免 KeyError 的默认字典键

IE中Json响应下载(7~10)

在 JSON 编码的 HTML5 数据属性中转义/编码单引号

如何在 Perl 中将简单的哈希转换为 json?

如何在已声明的 JSON 对象中添加键值对

MVC JsonResult camelCase 序列化

JSON.stringify 向我的 Json 对象添加额外的 \ 和 "" 的问题