RJsonを触ってみました。

動機

個人的に作成中のアプリケーションでJsonが必要になったのでHaskellJsonモジュールについて調べてみたところ、
RJsonがREADMEが充実していて良さそうだったので触ってみました。
備忘録として記事にしておきます。

導入

cabal install RJson

使い方

Google Translateの結果のJsonを例に書きます。
まず結果のJsonに含まれるデータを表す型を作ります。

data GoogleTranslateJson = GoogleTranslateJson {
     _data :: GoogleTranslateJsonData
} deriving Show

data GoogleTranslateJsonData = GoogleTranslateJsonData {
     _translations :: [GoogleTranslateJsonTranslation]
} deriving Show

data GoogleTranslateJsonTranslation = GoogleTranslateJsonTranslation {
     _translatedText :: String
} deriving Show

次にこの型をRJsonのシステムに登録します。

$(derive[''GoogleTranslateJson, ''GoogleTranslateJsonData, ''GoogleTranslateJsonTranslation])

後は使用するソースで以下のオプションを有効にし、必要なモジュールをimportします。

{-# OPTIONS_GHC
    -XTemplateHaskell
    -XFlexibleInstances
    -XMultiParamTypeClasses
    -XFlexibleContexts
    -XUndecidableInstances #-}

import Text.RJson
import Data.Generics.SYB.WithClass.Basics
import Data.Generics.SYB.WithClass.Derive

これだけで、

toJson GoogleTranslateJson{ _data = GoogleTranslateJsonData{ _translations = [ GoogleTranslateJsonTranslation{ _translatedText = "fleurs" } ] } }
fromJsonString (undefined :: GoogleTranslateJson) "{\"data\": {\"translations\": [{\"translatedText\": \"fleurs\"}]}}"

という書き出し、読み込み用の二つの関数が使えるようになります。

便利そうです。

テストしたバージョン

  1. RJson-0.3.7
  2. GHC 6.12.1

一応テストしたソースも貼って置きます。

ソース

{-# OPTIONS_GHC
    -XTemplateHaskell
    -XFlexibleInstances
    -XMultiParamTypeClasses
    -XFlexibleContexts
    -XUndecidableInstances #-}

import Text.RJson
import Data.Generics.SYB.WithClass.Basics
import Data.Generics.SYB.WithClass.Derive

-- 型定義
data GoogleTranslateJson = GoogleTranslateJson {
     _data :: GoogleTranslateJsonData
} deriving Show

data GoogleTranslateJsonData = GoogleTranslateJsonData {
     _translations :: [GoogleTranslateJsonTranslation]
} deriving Show

data GoogleTranslateJsonTranslation = GoogleTranslateJsonTranslation {
     _translatedText :: String
} deriving Show

-- 登録
$(derive[''GoogleTranslateJson, ''GoogleTranslateJsonData, ''GoogleTranslateJsonTranslation])

-- テスト
main = do
          putStrLn $ show tojson
          case fromjsonStr of
               Right v ->
                   putStrLn $ show v
               Left e ->
                   putStrLn e
       where
          tojson = toJson GoogleTranslateJson{ _data = GoogleTranslateJsonData{ _translations = [ GoogleTranslateJsonTranslation{ _translatedText = "fleurs" } ] } }
          fromjsonStr = fromJsonString (undefined :: GoogleTranslateJson) "{\"data\": {\"translations\": [{\"translatedText\": \"fleurs\"}]}}"