活动模型序列化程序 -- 自定义 JSON 响应
Active Model Serializers -- Customizing JSON response
在这里快速提问。尝试搜索无果。
我正在努力为我当前的项目启动 RESTful API。我发现 Rails 绝对是这个目的的宠儿,所以检查另一个标记 rails' 真棒!
然而,我在为 /users 设计我当前的 API 响应时遇到了障碍,这是一种应该 return 一个 JSON 用户对象数组的方法:
我的用户模型:
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable
has_many :favorites
has_many :reservations
has_many :venues, through: :favorites
has_many :venues, through: :reservations
belongs_to :gender
belongs_to :city
belongs_to :role
has_one :avatar
has_many :payments
has_one :payment_history
has_many :promotion_claims
has_many :social_identifiers
end
我的路线:
Rails.application.routes.draw do
namespace :api, defaults: { format: :json } do
namespace :v1 do
devise_for :users
..........................
resources :roles
resources :genders
resources :cities
#Users method
get 'users', to: "users#index"
end
end
我的控制器:
class API::V1::UsersController < API::V1::ApplicationController
before_action :set_address, only: [:show, :edit, :update, :destroy]
# GET /users
# GET /users.json
def index
@users = User.all
render json: @users
end
end
我的序列化程序:
class UserSerializer < ActiveModel::Serializer
attributes :id, :first_name, :last_name, :cellphone, :email, :birthday, :username
has_one :gender
has_one :city
has_one :role
end
class GenderSerializer < ActiveModel::Serializer
attributes :name
end
class CitySerializer < ActiveModel::Serializer
attributes :name
end
class RoleSerializer < ActiveModel::Serializer
attributes :name
end
就我得到的 json 响应而言,这实现了一个非常令人满意的结果:
// GET http://localhost:3000/api/v1/users
[
{
"id": 1,
"first_name": "Richmond",
"last_name": "Huels",
"cellphone": "29 8244 9100",
"email": "coy.muller@medhurst.us",
"birthday": "2011-02-23T19:24:00.151Z",
"username": "alba.ortiz",
"gender": {
"name": "Male"
},
"city": {
"name": "San Pedro Garza García"
},
"role": {
"name": "admin"
}
},
但是,我希望我的 JSON 响应更像是:
// 20160225162402
// GET http://localhost:3000/api/v1/users
[
{
"id": 1,
"first_name": "Richmond",
"last_name": "Huels",
"cellphone": "29 8244 9100",
"email": "coy.muller@medhurst.us",
"birthday": "2011-02-23T19:24:00.151Z",
"username": "alba.ortiz",
"gender": "Male",
"city": "San Pedro Garza García",
"role": "rp"
},
我尝试重写 UserSerializer 中的属性方法并创建它,这样我就可以在 return 之前用 json 散列做任何我想做的事,但它没有用:
#attributes override to get the right format for the response
def attributes
data = super
data[:city] = data[:city][:name]
data[:gender] = data[:gender][:name]
data[:role] = data[:city][:name]
data
end
有什么方法可以实现我的 API 所需要的吗?
感谢 rubyists,你们统治并继续保持惊人!
如果你想将结果合并到单个散列中。
您可以使用 flatten 方法,示例。
s = [ 1, 2, 3 ] #=> [1, 2, 3]
t = [ 4, 5, 6, [7, 8] ] #=> [4, 5, 6, [7, 8]]
a = [ s, t, 9, 10 ] #=> [[1, 2, 3], [4, 5, 6, [7, 8]], 9, 10]
a.flatten #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
在你的例子中,在获得所有结果并将其传递给变量“data”后
data.flatten
我想通了:
我觉得这是一种 hacky 方法,因为基本上,我没有为与我的用户模型相关的模型使用序列化器,而是覆盖了属性方法,但我所做的是删除了所有来自我的用户序列化程序的关系然后我完全按照我之前写的那样覆盖属性:
class UserSerializer < ActiveModel::Serializer
attributes :id, :first_name, :last_name, :gender, :cellphone, :city, :email, :birthday, :username, :role
def attributes
data = super
data[:gender] = data[:gender][:name]
data[:city] = data[:city][:name]
data[:role] = data[:role][:name]
data
end
end
这让我得到了我完全需要的 JSON 响应:
编辑:我找到了一个更好的方法:
我的序列化器:
class UserSerializer < ActiveModel::Serializer
attributes :id, :first_name, :last_name, :gender, :cellphone, :city, :email, :birthday, :username, :role
def gender
return object.gender.name
end
def city
return object.city.name
end
def role
return object.role.name
end
end
在我看来,更简洁、更面向对象。
确保所有其他序列化程序都已到位,并且模型对其字段进行了适当的验证。
结果完全一样:
在这里快速提问。尝试搜索无果。
我正在努力为我当前的项目启动 RESTful API。我发现 Rails 绝对是这个目的的宠儿,所以检查另一个标记 rails' 真棒!
然而,我在为 /users 设计我当前的 API 响应时遇到了障碍,这是一种应该 return 一个 JSON 用户对象数组的方法:
我的用户模型:
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable
has_many :favorites
has_many :reservations
has_many :venues, through: :favorites
has_many :venues, through: :reservations
belongs_to :gender
belongs_to :city
belongs_to :role
has_one :avatar
has_many :payments
has_one :payment_history
has_many :promotion_claims
has_many :social_identifiers
end
我的路线:
Rails.application.routes.draw do
namespace :api, defaults: { format: :json } do
namespace :v1 do
devise_for :users
..........................
resources :roles
resources :genders
resources :cities
#Users method
get 'users', to: "users#index"
end
end
我的控制器:
class API::V1::UsersController < API::V1::ApplicationController
before_action :set_address, only: [:show, :edit, :update, :destroy]
# GET /users
# GET /users.json
def index
@users = User.all
render json: @users
end
end
我的序列化程序:
class UserSerializer < ActiveModel::Serializer
attributes :id, :first_name, :last_name, :cellphone, :email, :birthday, :username
has_one :gender
has_one :city
has_one :role
end
class GenderSerializer < ActiveModel::Serializer
attributes :name
end
class CitySerializer < ActiveModel::Serializer
attributes :name
end
class RoleSerializer < ActiveModel::Serializer
attributes :name
end
就我得到的 json 响应而言,这实现了一个非常令人满意的结果:
// GET http://localhost:3000/api/v1/users
[
{
"id": 1,
"first_name": "Richmond",
"last_name": "Huels",
"cellphone": "29 8244 9100",
"email": "coy.muller@medhurst.us",
"birthday": "2011-02-23T19:24:00.151Z",
"username": "alba.ortiz",
"gender": {
"name": "Male"
},
"city": {
"name": "San Pedro Garza García"
},
"role": {
"name": "admin"
}
},
但是,我希望我的 JSON 响应更像是:
// 20160225162402
// GET http://localhost:3000/api/v1/users
[
{
"id": 1,
"first_name": "Richmond",
"last_name": "Huels",
"cellphone": "29 8244 9100",
"email": "coy.muller@medhurst.us",
"birthday": "2011-02-23T19:24:00.151Z",
"username": "alba.ortiz",
"gender": "Male",
"city": "San Pedro Garza García",
"role": "rp"
},
我尝试重写 UserSerializer 中的属性方法并创建它,这样我就可以在 return 之前用 json 散列做任何我想做的事,但它没有用:
#attributes override to get the right format for the response
def attributes
data = super
data[:city] = data[:city][:name]
data[:gender] = data[:gender][:name]
data[:role] = data[:city][:name]
data
end
有什么方法可以实现我的 API 所需要的吗?
感谢 rubyists,你们统治并继续保持惊人!
如果你想将结果合并到单个散列中。
您可以使用 flatten 方法,示例。
s = [ 1, 2, 3 ] #=> [1, 2, 3]
t = [ 4, 5, 6, [7, 8] ] #=> [4, 5, 6, [7, 8]]
a = [ s, t, 9, 10 ] #=> [[1, 2, 3], [4, 5, 6, [7, 8]], 9, 10]
a.flatten #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
在你的例子中,在获得所有结果并将其传递给变量“data”后
data.flatten
我想通了:
我觉得这是一种 hacky 方法,因为基本上,我没有为与我的用户模型相关的模型使用序列化器,而是覆盖了属性方法,但我所做的是删除了所有来自我的用户序列化程序的关系然后我完全按照我之前写的那样覆盖属性:
class UserSerializer < ActiveModel::Serializer
attributes :id, :first_name, :last_name, :gender, :cellphone, :city, :email, :birthday, :username, :role
def attributes
data = super
data[:gender] = data[:gender][:name]
data[:city] = data[:city][:name]
data[:role] = data[:role][:name]
data
end
end
这让我得到了我完全需要的 JSON 响应:
编辑:我找到了一个更好的方法:
我的序列化器:
class UserSerializer < ActiveModel::Serializer
attributes :id, :first_name, :last_name, :gender, :cellphone, :city, :email, :birthday, :username, :role
def gender
return object.gender.name
end
def city
return object.city.name
end
def role
return object.role.name
end
end
在我看来,更简洁、更面向对象。
确保所有其他序列化程序都已到位,并且模型对其字段进行了适当的验证。
结果完全一样: