我一直在挖掘FastJsonAPI。效果很好。
可以根据每个对象设置set_type 串行化定义吗?
也就是说,我使用的是Rails STI (单表继承)。我有一组基本对象和派生对象的混合集合,我希望每个对象都有不同的类型。
这是一个假的JSON输出示例,我想:
{
"data": [
{
"attributes": {
"title": "Generic Vehicle"
},
"id": "1",
"type": "vehicle"
},
{
"attributes": {
"title": "Fast Car"
},
"id": "2",
"type": "car"
},
{
"attributes": {
"title": "Slow Car"
},
"id": "3",
"type": "car"
},
{
"attributes": {
"title": "Motorcycle"
},
"id": "4",
"type": "motorcycle"
}
]
}当然,我有一个对象type属性可以使用,因为我使用的是STI。但是我不想使用它作为属性:我想使用它作为外部type,就像上面的JSON一样。
串行化器:
class VehicleSerializer
include FastJsonapi::ObjectSerializer
set_type :vehicle # can I tie this to individual objects, right here?
attributes :title
end
class CarSerializer < VehicleSerializer
set_type :car
attributes :title
end
class MotorcycleSerializer < VehicleSerializer
set_type :motorcycle
attributes :title
end
class TruckSerializer < VehicleSerializer
set_type :truck
attributes :title
end您看,我有一些控制器只从单个对象type中提取,对于它们来说,单个CarSerializer或其他什么都很好用。问题是,当我使用这样的控制器时,它在索引方法中聚合多个车辆类型:
require_relative '../serializers/serializers.rb'
class MultiVehiclesController < ApplicationController
def index
@vehicles = Vehicle.where(type: ["Car", "Motorcycle"])
# perhaps there's a way to modify the following line to use a different serializer for each item in the rendered query?
render json: VehicleSerializer.new(@vehicles).serializable_hash
end
def show
@vehicle = Vehicle.find(params[:id])
# I suppose here as well:
render json: VehicleSerializer.new(@vehicle).serializable_hash
end
end发布于 2018-03-21 20:23:19
发布于 2020-11-29 12:04:53
我也有STI,并希望在呈现不同类的集合时使用适当的type。最后,我使用了一个自定义序列化程序来覆盖hash_for_collection。在该方法中,可以查找特定的集合项序列化程序并调用其record_hash。
这比fast_jsonapi /jsonapi序列化器实现慢一点,但是现在data集合中的每个项都有正确的type。
class MixedCollectionSerializer < ApplicationSerializer
include SerializerResolverHelper
def hash_for_collection
serializable_hash = {}
data = []
included = []
fieldset = @fieldsets[self.class.record_type.to_sym]
@resource.each do |record|
record_klazz = jsonapi_serializer_class_resolver(record,false)
data << record_klazz.record_hash(record, fieldset, @includes, @params)
included.concat record_klazz.get_included_records(record, @includes, @known_included_objects, @fieldsets, @params) if @includes.present?
end
serializable_hash[:data] = data
serializable_hash[:included] = included if @includes.present?
serializable_hash[:meta] = @meta if @meta.present?
serializable_hash[:links] = @links if @links.present?
serializable_hash
end
endmodule SerializerResolverHelper
def jsonapi_serializer_class_resolver(resource, is_collection)
if resource.respond_to?(:first)
# if it is a collection and it contailns different types
first_item_class = resource.first.class
return MixedCollectionSerializer if resource.any? { |item| item.class != first_item_class }
end
JSONAPI::Rails.serializer_class(resource, is_collection)
rescue NameError
# if use STI it is necessary to resolve serializers manually
resource = resource.first if is_collection && resource.respond_to?(:first)
resource_name = case
when resource.is_a?(Vehicle) then resource.type.to_s
# another STI parent classes ...
end
"#{resource_name}Serializer".constantize if resource_name.present?
end
endhttps://stackoverflow.com/questions/49332715
复制相似问题