ActiveModel :: Serializer针对空的has_one关系(而不是JSON)返回null

时间:2019-11-15 09:27:05

标签: ruby-on-rails json serializer

问题

我们的API将返回JSON对象(但不返回JSON API)。 我们如何更改ActiveModel :: Serializer以创建数据属性设置为null的JSON对象?

对于一个空(has_one关系)资源,我们得到的响应为NULL,但我们希望它采用JSON格式{data:NULL},就像我们收到的非空资源{data:{... }},或者用于列表(has_many关系)资源{data:[]}。

我们尝试过的

我们使用ActiveModel :: Serialiser并指定要命名为“数据”而不是资源名称的键(类似于JSON API,但是数据的内容是实体的直接JSON表示形式。)

模型

class User < ApplicationRecord
  has_one :profile

  def serializer_class
    V1::UserSerializer
  end
end

class Profile < ApplicationRecord
  belongs_to :user

  def serializer_class
    V1::ProfileSerializer
  end
end

序列化器

class ApplicationSerializer < ActiveModel::Serializer
  def json_key
    'data'
  end
end

class UserSerializer < ApplicationSerializer
  attributes :id, :created_at, :updated_at #we do not include the profile here
end

class ProfileSerializer < ApplicationSerializer
  attributes :id, :created_at, :updated_at
end

控制器

class ProfilesController < ::ApplicationController
  before_action :authenticate_user!
  def show
    @profile = current_user.profile
    render json: @profile
  end
end

回复

对于一个空资源(GET / profile),我们得到了(对我们来说是错误的)响应:

NULL

我们正确地获得了一个非空资源的响应,它看起来像这样(不是JSON API):

{
  data: {
    id: ...,
    createdAt: ...,
    updatedAt: ...
  }
}

我们想要的东西

我们希望在尚未关联任何实体的情况下,以这种方式设置响应格式:

{
  data: null
}

2 个答案:

答案 0 :(得分:0)

我发现此(解决方法)解决方案解决了该问题:

  def show
    @profile = current_user.profile
    if @profile
      render json: @profile
    else
      render json: { data: nil }
    end
  end

答案 1 :(得分:0)

我们决定采用这种更严格的解决方案,在其中我们以404响应以获取空资源。

def show
  @profile = current_user.profile
  raise ActiveRecord::RecordNotFound unless @profile
  render json: @profile
end

然后在ApplicationController中添加此代码以处理异常:

rescue_from ActiveRecord::RecordNotFound do |exception|
  render json: Api::ErrorSerializer.serialize(:not_found, 'Not Found'),
         status: :not_found
end