[Yesod] Jsonを返す

[Yesod] Jsonを返す

Jsonを返すリソース

まずは適当なjsonを返すように定義してみます。

getJsonR :: Handler Value
getJsonR = jsonToRepJson $ object ["data" .= ("val" :: Text)]
  • 型を Handler Value とします。
  • jsonToRepJsonでobjectで作ったデータをJsonとして返している… みたいな感じです。

参考にしたURLここなんですが、型をHandler RepJsonにしていると、うまく行きませんでした。ただここを見てみると、どうも古いバージョンでのものらしく、Handler Valueに変えろとあったので変更したらうまくいきました。

独自に定義したデータJsonとして返す

モデルを定義し、データをJsonにして返してみます。そのためのモデルをconfig/modelsに定義します。モデルの名称の隣に、jsonとつける必要があります。

config/models

Book json
  title Text
  author Text
  pageCount Int

このBookのデータをJsonに変換し返すようにリソースを定義します。

getJsonR :: Handler Value
getJsonR = do
  books <- runDB $ selectList [] [Asc BookId]
  jsonToRepJson $ books

これでDBから取得したBookのデータをJsonとして返すことができます。例として次のようなデータが返ってきます。(整形しています。)

[
    {
        "author": "著者1",
        "id": 1,
        "title": "タイトル1",
        "pageCount": 1111
    },
    {
        "author": "著者2",
        "id": 2,
        "title": "タイトル2",
        "pageCount": 2222
    }
]

モデル以外のでデータをJsonとして返す

例えば、Personという型のデータをHandlerで独自に定義し、それをJsonとして返してみます。これには一工夫が必要になります。

--import Data.Aeson

data Person = Person
  { name :: Text
  , age  :: Int
  }

instance ToJSON Person where
  toJSON Person {..} = object
    [ "name" .= name
    , "age"  .= age
    ]

getJsonR :: Handler Value
getJsonR = do
  let taro = Person { name = "太郎", age = 12 }
  jsonToRepJson $ taro
  • まずData.Aesonをインポートする必要があります。が、実際はYesodのプロジェクトではすでにインポートされているようで、なくても動きます。
  • 次に独自のデータ型を定義します。
  • ToJSON 型クラスのインスタンスにし、toJSON関数を定義します。そして、各フィールドがどのように出力されるべきかを指定します。
  • あとはデータをjsonToRepJsonを使ってやるだけです。
{"age":12,"name":"太郎"}

Jsonのデータが実際のフィールドの順序と異なり、アルファベット順となっていますが、これが仕様です。JSONはデータの順序は関係ないので問題ないようです。

参考URL

Haskellカテゴリの最新記事