Swagger (OpenAPI 3) schema based serializer.
Add this line to your application's Gemfile:
gem 'swagger-serializer'
And then execute:
$ bundle
Or install it yourself as:
$ gem install swagger-serializer
use "swagger-dsl"!
Load it in initializer.
# config/initializers/swagger_serializer.rb
if Rails.application.config.eager_load
Swagger::DSL.current.config.lazy_define_paths = true
Rails.application.config.after_initialize do
Rails.application.reload_routes!
Swagger::DSL.current.define_paths!
Swagger::Schema.current = Swagger::Schema.new(Swagger::DSL.current.resolved)
end
else
Swagger::Schema.current = Swagger::Schema.new(Swagger::DSL.current)
Swagger::Serializer::Store.current.serialize_options[:resolver] = Swagger::DSL.current.resolver
Swagger::Serializer::Store.current.deserialize_options[:resolver] = Swagger::DSL.current.resolver
end
Use it in controllers.
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
include Swagger::Serializer::RailsController
extend Swagger::DSL::RailsController
def render_ok(data, context = nil)
render_as_schema 200, :json, data, context
end
def render_bad(data, context = nil)
render_as_schema 400, :json, data, context
end
end
# app/controllers/users_controller.rb
class UsersController < ApplicationController
swagger :index do
render 200 do
array! { cref! UserSerializer }
end
end
def index
render_ok User.all
end
swagger :show do
params do
path :id, schema: :integer
end
render 200 do
cref! UserSerializer
end
end
def show
render_ok User.find(schema_params[:id])
end
swagger :create do
body format: [:form, :json] do
user :object do
name :string
end
end
render 200 do
cref! UserSerializer
end
render 400 do
additionalProperties! do
array! { string! }
end
end
end
def create
@user = User.new(schema_params[:user])
if @user.save
render_ok @user
else
render_bad @user.errors
end
end
swagger :update do
params do
path :id, schema: :string
end
body format: [:form, :json] do
user :object do
name :string
end
end
render 200 do
cref! UserSerializer
end
render 400 do
additionalProperties! do
array! { string! }
end
end
end
def update
@user = User.find(schema_params[:id])
if @user.update(schema_params[:user])
render_ok @user
else
render_bad @user.errors
end
end
swagger :destroy do
params do
path :id, schema: :string
end
end
def destroy
@user.destroy!
head :no_content
end
end
Would you want to customize serialization?
# app/serializers/base_serializer.rb
class BaseSerializer
include Swagger::Serializer
extend Swagger::DSL::Serializer
end
# app/serializers/user_serializer.rb
class UserSerializer < BaseSerializer
swagger do
id :integer
name :string, optional: true
end
def name
"#{@model.name}!!!!"
end
end
Now you can get { "id" => 42, "name" => "me!!!!" }
.
This serializer class detection uses the schema's title
key.
If you want to use Foo::BarSerializer
, set Foo-Bar
to title
key.
The key is configurable by
# in config/initializers/swagger_serializer.rb
Swagger::Serializer::Store.current.serialize_options[:inject_key] = "my_inject_key"
Swagger::Serializer::Store.current.deserialize_options[:inject_key] = "my_inject_key"
Swagger::DSL.current.config.inject_key = "my_inject_key"
Sometimes model needs direct serialize.
# app/models/application_record.rb
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
include Swagger::Serializer::Model
end
Now you can get serialized result by p User.first.serialize
.
Write your OpenAPI spec.
# swagger.yml
openapi: 3.0.0
info:
title: example api
version: 0.1.0
components:
schemas:
User: &User
title: User
type: object
properties:
id:
type: integer
name:
type: string
required: [id]
paths:
/users:
get:
responses:
200:
content:
application/json:
schema:
type: array
items: *User
/users/{id}:
get:
responses:
200:
content:
application/json:
schema: *User
Load it in initializer.
# config/initializers/swagger_serializer.rb
Swagger::Schema.load_file_to_current(
__dir__ + "/../../swagger.yml",
)
Use it in controllers.
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
include Swagger::Serializer::RailsController
def render_ok(data, context = nil)
render_as_schema 200, :json, data, context
end
end
# app/controllers/users_controller.rb
class UsersController < ApplicationController
def index
render_ok User.all
end
def show
render_ok User.find(params[:id])
end
end
Would you want to customize serialization?
# app/serializers/base_serializer.rb
class BaseSerializer
include Swagger::Serializer
end
# app/serializers/user_serializer.rb
class UserSerializer < BaseSerializer
def name
"#{@model.name}!!!!"
end
end
Now you can get { "id" => 42, "name" => "me!!!!" }
.
Sometimes model needs direct serialize.
# app/models/application_record.rb
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
include Swagger::Serializer::Model
end
Now you can get serialized result by p User.first.serialize
.
Collection serialization sometimes needs context data for avoiding N+1 access or some other reason.
render_as_schema
's 4th parameter is the context that will be passed to serializers @context
.
# app/serializers/item_serializer.rb
class ItemSerializer < BaseSerializer
swagger do
id :integer
rate :integer
end
def rate
@context[:rates][id]
end
end
# app/controllers/items_controller.rb
class ItemsController < ApplicationController
swagger :index do
render 200 do
array! do
cref! ItemSerializer
end
end
end
def index
items = Item.all
rates = ItemRate.calc_item_rates(items)
render_ok items, { rates: rates }
end
end
After checking out the repo, run bin/setup
to install dependencies. Then, run rake spec
to run the tests. You can also run bin/console
for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install
. To release a new version, update the version number in version.rb
, and then run bundle exec rake release
, which will create a git tag for the version, push git commits and tags, and push the .gem
file to rubygems.org.
Bug reports and pull requests are welcome on GitHub at https://github.com/Narazaka/swagger-serializer.