Aeson: parse listed data types
How can I declare a FromJSON instance of the following datatype:
data Privacy = Everyone |
AllFriends |
FriendsOfFriends |
Self
So, the following line holds for an enumerated data type:
"EVERYONE" -> Everyone
"ALL_FRIENDS" -> AllFriends
"FRIENDS_OF_FRIENDS" -> FriendsOfFriends
"SELF" -> Self
_ -> Parsing error
A possible solution is outlined here , but I cannot compile this code.
Thank!
+3
source to share
3 answers
The FromJSON definition should read:
instance FromJSON Privacy where
parseJSON (Object v) = createPrivacy <$> (v .: "value")
Complete working example:
{-# LANGUAGE OverloadedStrings #-}
import Data.Text
import Data.Aeson
import Control.Applicative
import Control.Monad
data Privacy = Everyone |
AllFriends |
FriendsOfFriends |
Self
deriving (Show)
instance FromJSON Privacy where
parseJSON (Object v) = createPrivacy <$> (v .: "value")
parseJSON _ = mzero
createPrivacy :: String -> Privacy
createPrivacy "EVERYONE" = Everyone
createPrivacy "ALL_FRIENDS" = AllFriends
createPrivacy "FRIENDS_OF_FRIENDS" = FriendsOfFriends
createPrivacy "SELF" = Self
createPrivacy _ = error "Invalid privacy setting!"
main = do
let a = decode "{\"value\":\"ALL_FRIENDS\",\"foo\":12}" :: Maybe Privacy
print a
+2
source to share
The solution I found was to use pure
from Control.Applicative
.
import Control.Applicative ((<$>), (<*>), pure)
data Privacy = Everyone |
AllFriends |
FriendsOfFriends |
Self
instance FromJSON Privacy where
parseJSON (String s) = pure $ mkPrivacy s
parseJSON _ = fail "Failed to parse Privacy object"
instance ToJSON Privacy where
toJSON Everyone = "EVERYONE"
toJSON AllFriends = "ALL_FRIENDS"
toJSON FriendsOfFriends = "FRIENDS_OF_FRIENDS"
toJSON Self = "SELF"
mkPrivacy :: Text -> Privacy
mkPrivacy "EVERYONE" = Everyone
mkPrivacy "ALL_FRIENDS" = AllFriends
mkPrivacy "FRIENDS_OF_FRIENDS" = FriendsOfFriends
mkPrivacy "SELF" = Self
mkPrivacy _ = error "Invalid privacy token"
+1
source to share