type GoalDescription = Text
data GoalStatus = Created | Accomplished | InProgress | GivenUp deriving (Show , Eq , Generic )
data Goal = Goal {workspaceId ::WorkspaceId , goalId :: GoalId , description :: GoalDescription , status :: GoalStatus} deriving (Show , Eq , Generic )
instance ToJSON Goal where
toJSON (Goal {workspaceId, goalId ,description,status } ) = object [
"workspaceId" .= workspaceId,
"goalId" .= goalId,
"description" .= description,
"status" .= status]
instance FromJSON Goal where
parseJSON (Object jsonObject) = Goal <$> jsonObject .: "workspaceId" <*> jsonObject .: "goalId" <*> jsonObject .: "description" <*> jsonObject .: "status"
parseJSON _ = error $ "Json format not expected"
我想通过以下方式实现GoalStatus的FromJSON和ToJSON:Goal {.. status:"accomplished"}
或Goal {.. status:"inProgress"}
等...以某种方式,我不知道如何在没有键->值的情况下实现这些类型类结构... GoalStatus
仅应转换为String Text
,而值不附加键。
我有一个临时解决方案,我不得不添加一个不必要的名为“ value”的键:
instance ToJSON GoalStatus where
toJSON (Created) = object ["value" .= String "created"]
toJSON (InProgress) = object ["value" .= String "inProgress"]
toJSON (Accomplished) = object ["value" .= String "accomplished"]
toJSON (GivenUp) = object ["value" .= String "GivenUp"]
instance FromJSON GoalStatus where
parseJSON (Object o) = do
value <- o .: "value"
case value of
String status | (unpack status) == "created" -> return Created
String status | (unpack status) == "inProgress" -> return InProgress
String status | (unpack status) == "accomplished" -> return Accomplished
String status | (unpack status) == "accomplished" -> return GivenUp
_ -> error $ "Json format not expected"
parseJSON _ = error $ "Json format not expected"
答案 0 :(得分:4)
String !Text
是Value
的构造函数,并且object
的类型签名为[Pair] -> Value
,其中Pair
是(Text, Value)
。您可以使用String
在Value
中制作ToJSON
,然后在String
中解析时匹配FromJSON
的特定形状。
instance ToJSON GoalStatus where
toJSON (Created) = String "created"
toJSON (InProgress) = String "inProgress"
toJSON (Accomplished) = String "accomplished"
toJSON (GivenUp) = String "givenUp"
instance FromJSON GoalStatus where
parseJSON (String s) = case unpack s of
"created" -> return Created
"inProgress" -> return InProgress
"accomplished" -> return Accomplished
"givenUp" -> return GivenUp
_ -> error $ "Json format not expected"
parseJSON _ = error $ "Json format not expected"
答案 1 :(得分:0)
我不确定我是否理解这个问题。这是包含泛型实现的完整文件:
{-# LANGUAGE DeriveGeneric #-}
module Q54178405 where
import Data.Text
import Data.Aeson
import GHC.Generics
type WorkspaceId = Int
type GoalId = Int
type GoalDescription = Text
data GoalStatus =
Created | Accomplished | InProgress | GivenUp deriving (Show, Eq, Generic)
instance ToJSON GoalStatus
instance FromJSON GoalStatus
data Goal = Goal {
workspaceId ::WorkspaceId
, goalId :: GoalId
, description :: GoalDescription
, status :: GoalStatus}
deriving (Show, Eq, Generic)
instance ToJSON Goal
instance FromJSON Goal
以下是它在GHCi中的行为:
*Q54178405 Q54178405> encode $ Goal 42 1337 "foo" Accomplished
"{\"status\":\"Accomplished\",\"goalId\":1337,\"workspaceId\":42,\"description\":\"foo\"}"
*Q54178405 Q54178405> encode $ Goal 42 1337 "foo" GivenUp
"{\"status\":\"GivenUp\",\"goalId\":1337,\"workspaceId\":42,\"description\":\"foo\"}"
那不是你想要的吗?
实例也往返:
*Q54178405 Q54178405> decode $ encode $ Goal 42 1337 "foo" GivenUp :: Maybe Goal
Just (Goal {workspaceId = 42, goalId = 1337, description = "foo", status = GivenUp})
如果这不是您想要的,它将对一些带有所需输出的明确输入示例很有用。