You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Ruby on Rails 6.0.2中创建包含嵌套JSON对象的API响应?

嗨,我来帮你解决这个嵌套JSON响应的问题——完全不需要手动多次查询再拼接数据,Rails有一套顺畅的方案来处理这个需求,分几步走就行:

第一步:确保模型关联正确配置

首先得保证你的模型之间的关联关系是对的,这样Rails才能正确识别并加载关联数据:

  • 在app/models/event.rb里添加:
class Event < ApplicationRecord
  belongs_to :artist
  belongs_to :country
end
  • 在app/models/artist.rb里(可选,但建议加上方便反向查询):
class Artist < ApplicationRecord
  has_many :events
end
  • 在app/models/country.rb里:
class Country < ApplicationRecord
  has_many :events
end
第二步:用预加载避免N+1查询

直接查events后逐个调用.artist或.country会触发N+1次数据库查询(1次查events,每个event各查1次artist和country),性能很差。用includes可以一次性把关联数据都拉出来:
在app/controllers/events_controller.rb里,处理/events/artist/:artist_id路由的方法这么写:

def index_by_artist
  @events = Event.where(artist_id: params[:artist_id]).includes(:artist, :country)
  # 后续处理序列化返回
end

别忘了在config/routes.rb配置对应路由:

get '/events/artist/:artist_id', to: 'events#index_by_artist'
第三步:序列化生成嵌套JSON

有三种常用方式生成你要的嵌套JSON格式,选顺手的就行:

方式一:用Rails内置的as_json(快速简单)

直接在控制器里用as_json指定要包含的关联,还能自定义返回字段:

def index_by_artist
  @events = Event.where(artist_id: params[:artist_id]).includes(:artist, :country)
  render json: @events.as_json(
    only: [:id, :type],
    include: {
      artist: { only: [:id, :name] },
      country: { only: [:id, :name] }
    }
  )
end

这样返回的JSON结构完全符合你给出的示例。

方式二:用Jbuilder(自定义性强)

如果需要精细控制JSON结构,推荐用Jbuilder。创建视图文件app/views/events/index_by_artist.json.jbuilder,写入:

json.array! @events do |event|
  json.id event.id
  json.type event.type
  json.artist do
    json.id event.artist.id
    json.name event.artist.name
  end
  json.country do
    json.id event.country.id
    json.name event.country.name
  end
end

控制器里只需:

def index_by_artist
  @events = Event.where(artist_id: params[:artist_id]).includes(:artist, :country)
  render :index_by_artist
end

这种方式适合后续需要调整字段的场景,灵活性拉满。

方式三:用Active Model Serializers(结构化强)

如果API有大量序列化需求,Active Model Serializers(AMS)是更规范的选择。先把gem加进Gemfile:

gem 'active_model_serializers'

运行bundle install后,创建三个序列化器:

  • app/serializers/event_serializer.rb:
class EventSerializer < ActiveModel::Serializer
  attributes :id, :type
  has_one :artist
  has_one :country
end
  • app/serializers/artist_serializer.rb:
class ArtistSerializer < ActiveModel::Serializer
  attributes :id, :name
end
  • app/serializers/country_serializer.rb:
class CountrySerializer < ActiveModel::Serializer
  attributes :id, :name
end

最后控制器直接返回:

def index_by_artist
  @events = Event.where(artist_id: params[:artist_id]).includes(:artist, :country)
  render json: @events
end

AMS会自动生成符合要求的嵌套JSON结构。

总结

核心就是利用Rails的关联预加载(解决性能问题)和序列化工具(生成嵌套结构),完全不需要手动拼接数据。三种方式都能满足你的需求,根据场景选择就行~

内容的提问来源于stack exchange,提问作者justUrAverageProgrammer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 17:17:39