2014-11-22 100 views
3

我如何可以聲明以下數據類型的FromJSON的實例:埃宋:解析枚舉數據類型

data Privacy = Everyone | 
      AllFriends | 
      FriendsOfFriends | 
      Self 

所以,下面的字符串來枚舉數據類型很榮幸:

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

一可能的解決方案是暗示here,但我不能讓代碼編譯。

謝謝!

回答

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 
+0

感謝這個答案。因爲我有一個枚舉的數據類型作爲JSON對象的一個​​屬性,所以使用我在我的回答中描述的模式結束了。使用「值」需要我有額外的不必要的嵌套層次。然而你的代碼回答了我的問題。 – 2014-11-22 12:31:57

1

我找到的解決方案是使用pureControl.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" 
4

這樣涉及較少的樣板,但它可能無法做到高效由於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