LoginSignup
3
0

More than 3 years have passed since last update.

Haskell Aeson - Fast JSON parsing and encoding

Last updated at Posted at 2020-03-28

Haskell の JSONライブラリーである、Aeson のちょっとした紹介記事です。備忘録を兼ねてます。

1. プロジェクト構築

The Haskell Tool Stack

stack new my-project
cd my-project
stack setup
stack build
stack exec my-project-exe

2. ソースコード

まず最初の使用するパッケージを宣言しておきます。

package.yaml
dependencies:
- base >= 4.7 && < 5
- text
- aeson
- bytestring

ソースコードは以下のドキュメントのサンプルコードを使います。
aeson: Fast JSON parsing and encoding

src/AesonTest.hs
{-# LANGUAGE DeriveGeneric #-}

module AesonTest
    (
    ) where

import Data.Text
import Data.ByteString.Lazy
import Data.Aeson
import GHC.Generics

data Person = Person {
      name :: Text
    , age  :: Int
    } deriving (Generic, Show)


instance ToJSON Person
instance FromJSON Person

このソースコードのポイントは以下のinstance宣言です。

instance ToJSON Person
instance FromJSON Person

Person はToJSONFromJSON のinstanceであると宣言していますが、メソッド関数等の実装はありません。これは GHC の Generic拡張の恩恵で、以下のように Person が Generic を deriving しているからメソッド関数の省略が可能となっています。

Person
data Person = Person {
      name :: Text
    , age  :: Int
    } deriving (Generic, Show)

3. 実行

それではAesonを使って「JSON文字列 <=> Person型データ」のエンコード、デコードを確認してみましょう。

ghciを起動します。

stack ghci

AesonTest.hsをロードします。

*Main AesonTest Lib> :l AesonTest

encodeを実行します。

*AesonTest>  encode (Person {name = "Joe", age = 12})

<interactive>:2:25: error:
    ? Couldn't match expected type ‘Text’ with actual type ‘[Char]’
    ? In the ‘name’ field of a record
      In the first argument of ‘encode’, namely
        ‘(Person {name = "Joe", age = 12})’
      In the expression: encode (Person {name = "Joe", age = 12})

エラーとなりました。PersonのnameがTextなのに、入力が[Char]なのでunmatchとなったのです。GHCのOverloadedStrings拡張でこの辺の違いを吸収してもらいます。

OverloadedStrings
:set -XOverloadedStrings

再度、encode を実行します。OKですね。

*AesonTest>  encode (Person {name = "Joe", age = 12})
"{\"age\":12,\"name\":\"Joe\"}"

次の decode を実行します。これもOKです。

*AesonTest> decode "{\"name\":\"Joe\",\"age\":12}" :: Maybe Person
Just (Person {name = "Joe", age = 12})

最後に encode と decode の型を示しておきます。

import qualified Data.ByteString.Lazy as L
encode :: (ToJSON a) => a -> L.ByteString
decode :: (FromJSON a) => L.ByteString -> Maybe a

今回は以上です。

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0