JsonAPI

ぺったんはjsonを利用したAPIに対応している。というよりRailsの仕様に乗っかっている。Rails知ってる人はよまなくていい。

JsonAPIを使えば、ブラウザから操作せずとも直接データを操作できる。外部のプログラムからぺったんを楽しめる。

APIにはCRUD、つまり、create,read,update,deleteがあり、それぞれがHTTPのPOST,GET,PUT,DELETEに対応しているが、普通のブラウザからはGETしかできないので、手っ取り早くJsonAPIで遊ぶならcurlをインストールすると良い。

なお、railsではjsonでのやり取りを次のように規定している。

  • URLの末尾を拡張子のように.jsonする
  • リクエストヘッダはContent-Type: application/jsonとする

jsonデータの取得

例えば、ID:2のコマPanelのデータをcurlで取得するには次のようにする。

curl http://hostname/panels/2.json -X GET -H "Content-Type: application/json"

jsonでの投稿

例えば、コミックをcurlで作成するには次のようにする。このとき、作成するためのjsonデータはcomic_create.jsonファイルに用意されているものとする。

curl http://hostname/comics.json  -X POST -H "Content-Type: application/json" -d @comic_create.json

jsonでの更新

例えば、コミックをcurlで更新するには次のようにする。このとき、更新するためのjsonデータはcomic_update.jsonファイルに用意されているものとする。

curl http://hostname/comics.json  -X PUT -H "Content-Type: application/json" -d @comic_update.json

jsonでの削除

例えば、コミックをcurlで削除するには次のようにする。このとき、削除するためのjsonデータはcomic_delete.jsonファイルに用意されているものとする。

curl http://hostname/comics.json  -X DELETE -H "Content-Type: application/json" -d @comic_delete.json

※普通に削除するだけならDELETEメソッドだけで削除できる。jsonデータcomic_delete.jsonは必要ないはずだが、誰でも削除できるのはおかしな話なので、大抵の場合は認証がいるだろう。認証に必要なauth_tokenを渡すのだが、auth_tokenについては後述する。

jsonデータの作り方

jsonデータがどんなものかはググッてもらうとして、rails風なところを…

コミック作成に使ったcomic_create.jsonを例とすると次のようになる。

{
  "comic": {
    "title": "コミック作るテスト",
    "default_width": 400,
    "default_height": 200
  },
  "auth_token": "XXXXXXXXXXXXXXXX"
}
comicはコミックのmodel、titleなどはmodelのカラム。モデルの下に必要なカラムをキーにして値を記述する。

auth_tokenは認証が必要な操作をする場合に記述する。

auth_token

認証が必要な操作をする場合にはauth_tokenを用意する。auth_tokenはログイン後にプロフィールページを開くと書いてある。今のところは。

ネストしたデータの作り方

コマの投稿など、複数のモデルを一つのトランザクションで更新するような操作はjsonデータも複数のモデルについて記述しなければならない。

ネストされている子のデータはモデル名+_attributesをキーとしたハッシュ型の値をペアにして記述する。例えば、コマ絵のモデルpanel_picturesはpanel_pictures_attributesとなる。値側は複数のレコードを含むことが想定されるので、これもハッシュ型とする。こちらのキーは一意であれば何でもよく、値がレコードのデータである。文章じゃよくわからんので、コマ絵panel_pictures一つを含んだコマpanelを作成する場合の実際のデータを示す。

{
  "panel": {
    "border": 1,
    "comic_id": 5,
    "resource_picture_id": 1,
    "width": 400,
    "height": 200,
    "panel_pictures_attributes": {
      "new1": {
        "width": 100,
        "height": 103,
        "resource_picture_id": 4,
        "top_offset": 10,
        "left_offset": 135,
        "zindex": 1,
        "v": 1,
        "h": 0
      }
    }
  },
  "auth_token": "XXXXXXXXXXXXXXXX"
}

コマ絵が二枚だと、こんな感じ。

{
  "panel": {
    "border": 1,
    "comic_id": 5,
    "resource_picture_id": 1,
    "width": 400,
    "height": 200,
    "panel_pictures_attributes": {
      "new1": {
        "width": 100,
        "height": 103,
        "resource_picture_id": 4,
        "top_offset": 10,
        "left_offset": 135,
        "zindex": 1,
        "v": 1,
        "h": 0
      },
      "new2": {
        "width": 50,
        "height": 75,
        "resource_picture_id": 1,
        "top_offset": 30,
        "left_offset": 14,
        "zindex": 2,
        "v": 0,
        "h": 0
      }
    }
  },
  "auth_token": "XXXXXXXXXXXXXXXX"
}

キーの"new1"と"new2"は適当な命名なんであるが、こんな要領で列挙していけばまとめて作成できる。

では、次にコマ絵だけでなくフキダシとセリフも含むデータを作成してみるが、その前に各モデルの関係を整理しておく。

panel
  panel_pictures
  balloons
    speeches
だったね。
{
  "panel": {
    "border": 1,
    "comic_id": 5,
    "resource_picture_id": 1,
    "width": 400,
    "height": 200,
    "panel_pictures_attributes": {
      "new1": {
        "width": 100,
        "height": 103,
        "resource_picture_id": 4,
        "top_offset": 10,
        "left_offset": 135,
        "zindex": 3,
        "v": 1,
        "h": 0
      }
    },
    "balloons_attributes": {
      "newf1": {
        "balloon_template_id": 1,
        "resource_picture_id": 2,
        "tail": 1,
        "border": 1,
        "zindex": 5,
        "width": 81,
        "height": 63,
        "top_offset": 120,
        "left_offset": 35,
        "speeches_attributes": {
          "newf1s1": {
            "content": "test",
            "width": 61,
            "height": 43,
            "top_offset": 10,
            "left_offset": 10
          }
        }
      }
    }
  },
  "auth_token": "XXXXXXXXXXXXXXXX"
}

ネストしたデータの更新

あるコマのセリフを変更したいとする。セリフはspeechなのでspeeches経由で更新したいところだが、ぺったんの仕様はコマ全体で更新することになっているので、speechesのAPIは用意されていない。コマの変更はpanel経由で行う。このとき、jsonデータでは、どのように変更対象のセリフを指示するのだろうか。

結論としてはidをデータに含めて指定する。例えば、セリフのidが3のときは次のようになる。

{
  "panel": {
    "balloons_attributes": {
      "b2": {
        "id": 2,
        "speeches_attributes": {
          "s3": {
            "id": 3,
            "content": "modify"
          }
        }
      }
    }
  },
  "auth_token": "XXXXXXXXXXXXXXXX"
}

idが指定されていないと新規追加となってしまう。

ネストしたデータの削除

削除する場合、更新のときと同じようにidを指定しつつ_destroyにフラグを立てる。例えば、idが2のフキダシをコマから削除する場合、次のようにする。

{
  "panel": {
    "balloons_attributes": {
      "b2": {
        "id": 2,
        "_destroy": 1
      }
    }
  },
  "auth_token": "XXXXXXXXXXXXXXXX"
}

画像の投稿

auth_tokenを含みながらのファイル送信がよくわからん。いろんなパターンで試してみたが素直にはいかなかった。苦肉の策が画像データを一度Base64でエンコードしたものをテキストとして送信すること。次の例は当然エンコードテキストは省略されている。

{
  "original_picture": {
    "file": 
"iVBORw0KGgoAAAANSUhEUgAAAWIAAAF7CAYAAADohYEpAAAcW0lEQVR4nO3d
  :
  :
ghgAlP0/Bxl7hN5Zu0EAAAAASUVORK5CYII=
"
  },
  "auth_token": "XXXXXXXXXXXXXXXX"
}