7
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

JsonWorldを利用して生成したJSON Schemaを読み込み、JsonismでAPIを呼び出す

Posted at

@r7kamuraさん作のJsonWorldを利用して生成したJSON Schemaを、
同じく@r7kamuraさん作のJsonismで読み込み、APIを呼び出します

準備

JsonWorld, Jsonismについては@r7kamuraさん本人による下記のエントリをチェック

全てがJSONになる

サンプル

Railsを利用します

仕様

Railsのscaffoldで以下のモデルを作成しました。

attr type
People#name String
People#age Integer

Resourceクラス作成

app/api/resources/person.rb
require 'json_world'

module Api
  module Resources
    class Person
      include JsonWorld::DSL

      title 'Person'
      property(
        :id,
        description: '人物のid',
        example: 1,
        type: Integer,
      )

      property(
        :name,
        description: '人物の名前',
        example: "tanaka",
        type: String,
      )

      property(
        :age,
        description: '人物の年齢',
        example: 34,
        type: Integer,
      )

      link(
        :list,
        description: "全ての人物の一覧を取得します。",
        path: "/api/v1/people",
        rel: "instances",
      )

      link(
        :get,
        description: "人物を取得します。",
        path: "/api/v1/people/:id",
        rel: "self",
      )

      link(
        :create,
        description: "人物を登録します。",
        path: "/api/v1/people/:id",
        method: "POST",
        rel: "self",
        parameters: {
          name: {
            description: "人物の名前",
            example: "tanaka",
            type: String,
          },
          age: {
            description: "人物の年齢",
            example: 34,
            type: Integer,
          },
        },
      )

      link(
        :update,
        description: "人物を更新します。",
        path: "/api/v1/people/:id",
        method: "PATCH",
        rel: "self",
        parameters: {
          name: {
            description: "人物の名前",
            example: "tanaka",
            type: String,
          },
          age: {
            description: "人物の年齢",
            example: 34,
            type: Integer,
          },
        },
      )

      link(
        :delete,
        description: "人物を削除します。",
        path: "/api/v1/people/:id",
        method: "DELETE",
        rel: "self",
      )

      attr_reader :id, :name, :age

      # @param [Person] person
      def initialize(person, people)
        @id = person.id
        @name = person.name
        @age = person.age
        @people = people.age
      end
    end
  end
end

Schemaクラス作成

app/api/schema.rb
require 'json_world'
require "#{Rails.root}/app/api/resources/person.rb"

module Api
  class Schema
    include JsonWorld::DSL

    title 'Sample API v1 JSON Schema'
    description 'このスキーマ定義では、Sample API v1 のインターフェースをJSON Hyper Schema draft v4形式で表現しています。'

    property :people, links: true, type: Api::Resources::Person
    link href: "http://localhost:3000", rel: "self"
  end
end

Controller

app/controllers/api/v1/people_controller.rb
require "#{Rails.root}/app/controllers/application_controller.rb"
require "#{Rails.root}/app/api/resources/person.rb"

module Api
  module V1
    class PeopleController < ApplicationController
      before_action :set_person, only: [:show, :edit, :update, :destroy]
      # 動作確認用にCSRFを無効化しています
      skip_before_action :verify_authenticity_token

      # GET /api/v1/people
      def index
        render json: Person.all
      end

      # GET /api/v1/people/1
      def show
        render json: PersonResource.new(Person.find(params[:id]))
      end

      # POST /api/v1/people
      def create
        @person = Person.new(person_params)
        if @person.save
          render json: @person
        else
          render json: @person.errors, status: :unprocessable_entity
        end
      end

      # PATCH/PUT /api/v1/people/1
      def update
        if @person.update(person_params)
          render json: @person
        else
          render json: @person.errors, status: :unprocessable_entity
        end
      end

      # DELETE /api/v1/people/1
      def destroy
        @person.destroy
        head :no_content
      end

      private
        # Use callbacks to share common setup or constraints between actions.
        def set_person
          @person = Person.find(params[:id])
        end

        # Never trust parameters from the scary internet, only allow the white list through.
        def person_params
          params.require(:person).permit(:name, :age)
        end
    end
  end
end

routes.rb

Rails.application.routes.draw do
  namespace :api, format: 'json' do
    namespace :v1 do
      resources :people
    end
  end
  resources :people
  root to: 'people#index'
end

JSON Schemaを生成

Rails コンソールを利用してJSON Schemaを生成します。
出力した内容を sample_api_v1.json として保存します。

$ rails console
irb(main):002:0> puts Api::Schema.to_json_schema
{
  "description": "このスキーマ定義では、Sample API v1 のインターフェースをJSON Hyper Schema draft v4形式で表現しています。",
  "links": [
    {
      "method": "GET",
      "title": "{:href=>\"http://localhost:3000\", :rel=>\"self\"}"
    }
  ],
  "properties": {
    "people": {
      "links": [
        {
          "description": "全ての人物の一覧を取得します。",
          "href": "/api/v1/people",
          "method": "GET",
          "rel": "instances",
          "title": "list"
        },
        {
          "description": "人物を取得します。",
          "href": "/api/v1/people/:id",
          "method": "GET",
          "rel": "self",
          "title": "get"
        },
        {
          "description": "人物を登録します。",
          "href": "/api/v1/people/:id",
          "method": "POST",
          "rel": "self",
          "schema": {
            "properties": {
              "name": {
                "description": "人物の名前",
                "example": "tanaka",
                "type": "string"
              },
              "age": {
                "description": "人物の年齢",
                "example": 34,
                "type": "integer"
              }
            },
            "required": [
              "name",
              "age"
            ]
          },
          "title": "create"
        },
        {
          "description": "人物を更新します。",
          "href": "/api/v1/people/:id",
          "method": "PATCH",
          "rel": "self",
          "schema": {
            "properties": {
              "name": {
                "description": "人物の名前",
                "example": "tanaka",
                "type": "string"
              },
              "age": {
                "description": "人物の年齢",
                "example": 34,
                "type": "integer"
              }
            },
            "required": [
              "name",
              "age"
            ]
          },
          "title": "update"
        },
        {
          "description": "人物を削除します。",
          "href": "/api/v1/people/:id",
          "method": "DELETE",
          "rel": "self",
          "title": "delete"
        }
      ],
      "properties": {
        "id": {
          "description": "人物のid",
          "example": 1,
          "type": "integer"
        },
        "name": {
          "description": "人物の名前",
          "example": "tanaka",
          "type": "string"
        },
        "age": {
          "description": "人物の年齢",
          "example": 34,
          "type": "integer"
        }
      },
      "required": [
        "id",
        "name",
        "age"
      ],
      "title": "Person"
    }
  },
  "required": [
    "people"
  ],
  "title": "Sample API v1 JSON Schema"
}

動作確認

APIサーバー起動

$ rails s -b 0.0.0.0

Curlで疎通確認

$ curl http://localhost:3000/people/1.json
{"id":1,"name":"tanaka","age":23,"created_at":"2015-07-15T07:29:24.210Z","updated_at":"2015-07-15T07:29:24.210Z"}

Jsonismを使った、API呼び出しプログラムを作成

jsonism_sample.rb
require 'json'
require 'jsonism'
require 'pp'
schema_body = File.read("sample_api_v1.json")
schema = JSON.parse(schema_body)
client = Jsonism::Client.new(schema: schema)
puts client.methods(false)
pp client.list_person.body.map(&:to_hash)

Jsonismの動作確認

$ ruby jsonism_sample.rb
list_person
get_person
create_person
update_person
delete_person
[{"id"=>1,
  "name"=>"tanaka",
  "age"=>23,
  "created_at"=>"2015-07-15T07:29:24.210Z",
  "updated_at"=>"2015-07-15T07:29:24.210Z"},
 {"id"=>2,
  "name"=>"suzuki",
  "age"=>42,
  "created_at"=>"2015-07-15T07:29:34.840Z",
  "updated_at"=>"2015-07-15T07:29:34.840Z"},
 {"id"=>3,
  "name"=>"honda",
  "age"=>99,
  "created_at"=>"2015-07-21T06:27:41.264Z",
  "updated_at"=>"2015-07-21T06:27:41.264Z"},
 {"id"=>4,
  "name"=>"seki",
  "age"=>123,
  "created_at"=>"2015-07-28T07:46:24.991Z",
  "updated_at"=>"2015-07-28T07:46:24.991Z"},
 {"id"=>6,
  "name"=>"hoge",
  "age"=>123,
  "created_at"=>"2015-07-29T08:13:34.077Z",
  "updated_at"=>"2015-07-29T08:13:34.077Z"},
 {"id"=>8,
  "name"=>"hoge",
  "age"=>123,
  "created_at"=>"2015-07-29T08:34:03.411Z",
  "updated_at"=>"2015-07-29T08:34:03.411Z"}]

関連エントリ

外部資料

7
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?