Low commit activity in last 3 years
No release in over a year
Swagger (OpenAPI 3) schema based Serializer
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

Runtime

 Project Readme

Swagger::Serializer

Actions Status Gem Version

Swagger (OpenAPI 3) schema based serializer.

Installation

Add this line to your application's Gemfile:

gem 'swagger-serializer'

And then execute:

$ bundle

Or install it yourself as:

$ gem install swagger-serializer

Usage

Rails with swagger-dsl

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.

Rails with raw schema

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.

@context

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

Development

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.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/Narazaka/swagger-serializer.