HTMLでWeb APIをつくる


シングルページアプリケーションやモバイルアプリなどの普及により、サーバサイドではJSONを出力するWeb APIの必要性が高くなってきています。みなさんはどのようにWeb APIを作っているでしょうか。

## JSONはビュー

http://qiita.com/yuch_i/items/f6b04e2875f432f8f806
> RailsでJSON APIを定義する時、素のままでやろうとすると
> コントーラでto_jsonを呼んだり、モデルにas_jsonを定義したりすることになるかと思います。
>
> モデルに書くとAPIによって出力内容を変えたい場合にとても苦労します。
> API数が増えれば増えるほどモデルが複雑になっていきます。
>
> APIレスポンスとしてのJSONはコントローラやモデルに書くべきでしょうか？
> ビューに書いた方が自然ではないでしょうか？

これはRailsでの話ですが、Railsに限らず、フレームワークを使ってWeb APIを作るときに一般的にあてはまることだと思います。

## 変化に強い、再利用可能なAPIが必要

モデルをただJSONに変換すると、内部仕様であるモデルの属性名がそのまま露出します。意味はほとんど同じなのに、少しだけ違うAPIができてしまいます。さらに、属性名に依存してクライアントを作ってしまうと、モデルが変更されたときに壊れます。

今のWeb APIはそれぞれバラバラなフォーマットで定義されていて、共通な部分が少なすぎるという印象があります。APIが変わると、いつもゼロからコーディングしなければなりません。


では具体的にどうやって書けばいいでしょう？

## リンクは柔軟性を生む

リンクは、あるリソースを別のリソースと結びつけるものです。これにより、Web APIに柔軟性が生まれます。

クライアントを壊さずにAPIを変更するには、モデルの属性名を「変更されないもの＝標準の名前」に結びつければいいのです。
さらに、標準の名前に結びつけることで、少しずつ違うAPIが標準化され、再利用することができます。


## HTMLをテンプレートとして使う

JSONには、残念ながらリンクがありません。
しかし、リンクを持っていて、さらに標準の名前に結びつけるしくみも持っているフォーマットがあります。HTMLです。

そのしくみの1つとして、microdataがあります。
https://support.google.com/webmasters/answer/176035?hl=ja

```html
<div itemscope itemtype="http://schema.org/Person">
   私の名前は<span itemprop="name">東京太郎</span>ですが、 
   みんなから「<span itemprop="nickname">東太</span>」と呼ばれています。
   私のホームページは、 
   <a href="http://www.example.com" itemprop="url" rel="about">www.example.com</a> です。
   <span itemprop="address" itemscope
      itemtype="http://schema.org/Address">
      <span itemprop="locality">東京都</span>, 
      <span itemprop="region">港区</span> 
   </span>
   に住んでおり、<span itemprop="title">エンジニア</span>
   として <span itemprop="affiliation">ACME 社</span>に勤めています。
</div>
```

このマークアップで「[schema.org](http://schema.org/)」という標準の名前と結びつけることにより、GoogleはこのHTMLをクロールしたときデータとして認識し、検索結果に反映させます。

このHTMLは例えば、このようなJSONとみなすことができます。（これは[HAL](http://stateless.co/hal_specification.html)というフォーマットのJSONです）

```json
{
  "name":"東京太郎",
  "nickname":"東太",
  "url":"http://www.example.com",
  "title":"エンジニア",
  "affiliation":"ACME 社",
  "_links":{
    "type":{
      "href":"http://schema.org/Person"
    },
    "about":{
      "href":"http://www.example.com"
    }
  },
  "_embedded":{
    "address":[
      {
        "locality":"東京都",
        "region":"港区",
        "_links":{
          "type":{
            "href":"http://schema.org/Address"
          }
        }
      }
    ]
  }
}
```

このような形になると、もうWeb APIそのものです。つまり、HTMLはWeb APIとして使えるのです。元のモデルやHTMLが変更されても、microdataのマークアップさえ正しければ、同じJSONとみなすことができます。クライアントは壊れません。

JSONへの変換（もしくはデータの抽出）はサーバサイドでもクライアントサイドでも構いません。
クライアントサイドでは[microdata DOM API](http://www.whatwg.org/specs/web-apps/current-work/multipage/microdata.html#using-the-microdata-dom-api)という仕様が定義されていて、JavaScriptによる実装も存在します。

* Microdata-JS https://github.com/termi/Microdata-JS

microdata→JSON変換というアイデアは、以前から存在していて、新しいというわけではありません。

その他のJSON変換仕様の例：

* WHATWG http://www.whatwg.org/specs/web-apps/current-work/multipage/microdata.html#json
* JSON-LD http://www.w3.org/TR/json-ld/#microdata


俺俺フォーマットのJSONが濫造される中、なんとか簡単に統一的なフォーマットのJSONを作る方法はないか、と考えた結果、これにたどりつきました。


これからAPIを作るときには、HTMLを書くというのはどうでしょうか？

## 試作中

このアイデアが実現できるように、Railsで自動的に変換してJSON([HAL](http://stateless.co/hal_specification.html), [UBER](https://rawgit.com/mamund/media-types/master/uber-hypermedia.html))レスポンスを返すgemを現在試作しています。

* Hypermicrodata https://github.com/tkawa/hypermicrodata
* [RubyKaigi2014 | Missing in building Web APIs with Rails: Hypermedia](http://rubykaigi.org/2014/presentation/S-ToruKawamura)