Aeson でオプション値を含む JSON を扱う.
JSON の要素が全部が必須であれば簡単だけれども、そうでない場合が往々にしてある。公式のドキュメントにはサンプルがなかったので、ここにメモしておく。
値なし
Person の middleName がオプション値。型は Maybe Text。パース時に (.:?) を使用する。middleName が存在しなかった場合は、当然 Nothing だ。
{-# LANGUAGE OverloadedStrings #-} import Data.Aeson import Control.Applicative import Control.Monad import Data.Text import Data.ByteString.Lazy.Char8 data Person = Person { firstName :: Text , middleName :: Maybe Text , lastName :: Text } deriving Show instance FromJSON Person where parseJSON (Object v) = Person <$> v .: "firstName" <*> v .:? "middleName" <*> v .: "lastName" parseJSON _ = mzero instance ToJSON Person where toJSON (Person fname mname lname) = object [ "firstName" .= fname , "middleName" .= mname , "lastName" .= lname ] decodeWithMiddleName :: Maybe Person decodeWithMiddleName = decode "{\"firstName\":\"John\", \"middleName\":\"Lambda\", \"lastName\":\"Doe\"}" decodeWithoutMiddleName :: Maybe Person decodeWithoutMiddleName = decode "{\"firstName\":\"John\", \"lastName\":\"Doe\"}" encodeWithMiddleName :: ByteString encodeWithMiddleName = encode $ Person "John" (Just "Lambda") "Doe" encodeWithoutMiddleName :: ByteString encodeWithoutMiddleName = encode $ Person "John" Nothing "Doe"
実行結果。
*Main> encodeWithoutMiddleName "{\"middleName\":null,\"firstName\":\"John\",\"lastName\":\"Doe\"}" *Main> decodeWithMiddleName Just (Person {firstName = "John", middleName = Just "Lambda", lastName = "Doe"}) *Main> decodeWithoutMiddleName Just (Person {firstName = "John", middleName = Nothing, lastName = "Doe"}) *Main> encodeWithMiddleName "{\"middleName\":\"Lambda\",\"firstName\":\"John\",\"lastName\":\"Doe\"}" *Main> encodeWithoutMiddleName "{\"middleName\":null,\"firstName\":\"John\",\"lastName\":\"Doe\"}"
デフォルト値
パース時に値がなかった場合、デフォルト値を設定したい場合は (.!=) を使う。
{-# LANGUAGE OverloadedStrings #-} import Data.Aeson import Control.Applicative import Control.Monad import Data.Text data Person = Person { firstName :: Text , middleName :: Text -- Maybe じゃない , lastName :: Text } deriving Show instance FromJSON Person where parseJSON (Object v) = Person <$> v .: "firstName" <*> v .:? "middleName" .!= "Haskell" <*> -- デフォルト値 "Haskell" v .: "lastName" parseJSON _ = mzero decodeWithMiddleName :: Maybe Person decodeWithMiddleName = decode "{\"firstName\":\"John\", \"middleName\":\"Lambda\", \"lastName\":\"Doe\"}" decodeWithoutMiddleName :: Maybe Person decodeWithoutMiddleName = decode "{\"firstName\":\"John\", \"lastName\":\"Doe\"}"
結果
*Main> decodeWithMiddleName Just (Person {firstName = "John", middleName = "Lambda", lastName = "Doe"}) *Main> decodeWithoutMiddleName Just (Person {firstName = "John", middleName = "Haskell", lastName = "Doe"})