Aeson:解析枚举的数据类型

时间:2014-11-22 10:45:21

标签: json haskell aeson

如何声明以下数据类型的FromJSON实例:

data Privacy = Everyone | 
           AllFriends | 
           FriendsOfFriends | 
           Self

以下列出了枚举数据类型的字符串:

"EVERYONE" -> Everyone
"ALL_FRIENDS" -> AllFriends
"FRIENDS_OF_FRIENDS" -> FriendsOfFriends
"SELF" -> Self
_ -> Parsing error

一个可能的解决方案被暗示here,但我无法编译该代码。

谢谢!

3 个答案:

答案 0 :(得分:5)

这种方式涉及较少的样板,但由于T.unpack

,它可能效率不高
data Privacy = Everyone | AllFriends | FriendsOfFriends | Self deriving (Read, Show)

instance FromJSON Privacy where
  parseJSON (String s) = fmap read (pure $ T.unpack s)
  parseJSON _ = mzero

答案 1 :(得分:2)

FromJSON定义应为:

instance FromJSON Privacy where
     parseJSON (Object v) = createPrivacy <$> (v .: "value")

完整的工作示例:

{-# 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 :(得分:1)

我找到的解决方案是使用pure中的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"