Data.AesonでJSONを扱う
aesonのインストール手順
mkdir foo && cd foo
cabal sandbox init
cabal update
cabal install aeson
JSON文字列をaesonのJSON型(Value)に変換する
import Data.Aeson
import qualified Data.ByteString.Lazy as LBS
import Control.Applicative ((<$>))
main :: IO ()
main = do
maybeValue <- decode <$> LBS.readFile "test.json"
case (maybeValue :: Maybe Value) of
Just value -> print value
Nothing -> putStrLn "fail to decode."
JSON文字列をユーザ定義のデータ型に変換する
JSON文字列をユーザ定義型に変換する場合、ユーザ定義型をFromJSON型クラスのインスタンスとし、parseJSON関数を定義する必要がある。 parseJSON関数の型は、Value -> Parser (ユーザ定義型) である。 Applicativeスタイルで変換関数を定義できる他、GHCの拡張機能(DeriveGeneric)を使ってインスタンス宣言を自動化することもできる。
Lazy ByteStringからユーザ定義型への変換は、decode関数、または、eitherDecode関数で行う。
-- -*- coding: utf-8 -*-
{-# LANGUAGE OverloadedStrings #-}
import Data.Aeson
import qualified Data.ByteString.Lazy as LBS
import Control.Applicative ((<$>), (<*>))
import Control.Monad (mzero)
data Foo = Foo
{ hoge :: Integer
, fuga :: [String]
} deriving (Show)
instance FromJSON Foo where
parseJSON (Object v) = Foo
<$> v .: "hoge"
<*> v .: "fuga"
-- トップレベルの値がオブジェクトではない場合は、型エラーのためmzeroを返す
parseJSON _ = mzero
main :: IO ()
main = do
maybeFoo <- decode <$> LBS.readFile "test.json"
case (maybeFoo :: Maybe Foo) of
Just foo -> print foo
Nothing -> putStrLn "fail to decode."
eitherFoo <- eitherDecode <$> LBS.readFile "test.json"
case (eitherFoo :: Either String Foo) of
Right foo -> print foo
Left msg -> putStrLn msg
test.jsonの内容
{
"hoge" : 1,
"fuga" : ["fugaValue1", "fugaValue2"]
}
実行結果
> cabal exec runhaskell fromJson.hs Foo {hoge = 1, fuga = ["fugaValue1","fugaValue2"]} Foo {hoge = 1, fuga = ["fugaValue1","fugaValue2"]}
DeriveGenericを使用した場合
{-# LANGUAGE DeriveGeneric #-}
import GHC.Generics
import Data.Aeson
import qualified Data.ByteString.Lazy as LBS
import Control.Applicative ((<$>), (<*>))
data Foo = Foo
{ hoge :: Integer
, fuga :: [String]
} deriving (Show, Generic)
instance FromJSON Foo
main :: IO ()
main = do
maybeFoo <- decode <$> LBS.readFile "test.json"
case (maybeFoo :: Maybe Foo) of
Just foo -> print foo
Nothing -> putStrLn "fail to decode."
ユーザ定義のデータ型をJSON文字列に変換する
ユーザ定義型をJSON文字列に変換する場合、ユーザ定義型をToJSONクラスのインスタンスにして、encode関数を使ってユーザ定義型をLazy ByteStringに変換する。
{-# LANGUAGE OverloadedStrings #-}
import Data.Aeson
import Data.ByteString.Lazy.Char8 as LBS
data Coord = Coord
{ x :: Double
, y :: Double
} deriving (Show)
instance ToJSON Coord where
toJSON (Coord x y) = object ["x" .= x, "y" .= y]
main :: IO ()
main = do
LBS.putStrLn . encode $ Coord 1.0 2.0
DeriveGeneric拡張を使って、ToJSONクラスのインスタンス宣言を自動化することもできる。
{-# LANGUAGE DeriveGeneric #-}
import GHC.Generics
import Data.Aeson
import Data.ByteString.Lazy.Char8 as LBS
data Coord = Coord
{ x :: Double
, y :: Double
} deriving (Show, Generic)
instance ToJSON Coord
main :: IO ()
main = do
LBS.putStrLn . encode $ Coord 1.0 2.0