使用Data.Aeson根据字段的值解码json

时间:2018-09-10 14:50:32

标签: haskell

您将如何实现这种Sum类型的FromJson?

data CommandRequest = CreateWorkspace {commandId :: UUID , workspaceId ::UUID }
                 | IntroduceIdea {commandId :: UUID , workspaceId ::UUID , ideaContent :: String}

instance ToJSON CommandRequest where
   toJSON (CreateWorkspace commandId workspaceId) = object [
          "commandId" .= commandId,
          "workspaceId" .= workspaceId,
          "commandName" .= pack "createWorkspace"]
   toJSON (IntroduceIdea commandId workspaceId ideaContent) = object [
             "commandId" .= commandId,
             "workspaceId" .= workspaceId,
             "commandName" .= pack "introduceIdea",
             "ideaContent" .= ideaContent
             ]

instance FromJSON CommandRequest  where ... ?

因此,基于commandName字段commandName,我将能够重新构建命令。

更新:在你们的帮助下,结果如下:

instance FromJSON CommandRequest  where

parseJSON (Object jsonObject) = do
         commandName <- jsonObject .: "commandName"
         case commandName of
              Just (String "createWorkspace") -> CreateWorkspace
                  <$> jsonObject .: "commandId"
                  <*> jsonObject .: "workspaceId"
              Just (String "introduceIdea") -> IntroduceIdea
                  <$> jsonObject .: "commandId"
                  <*> jsonObject .: "workspaceId"
                  <*> jsonObject .: "ideaContent"
              Just (String unknownCommandName) -> error $ "Command unknown : " ++ unpack unknownCommandName
              Nothing -> error $ "Command name not provided"

1 个答案:

答案 0 :(得分:5)

只需通过commandName看一下(.:),然后决定要做什么。所以:

instance FromJSON CommandRequest  where
    parseJSON (Object o) = do
        commandName <- o .: "commandName"
        case commandName :: String of
            "createWorkspace" -> liftA2 CreateWorkspace (o .: "commandId") (o .: "workspaceId")
            "introduceIdea" -> liftA3 IntroduceIdea (o .: "commandId") (o .: "workspaceId") (o .: "ideaContent")
            _ -> typeMismatch "wrongo" (Object o)
    parseJSON v = typeMismatch "double wrongo" v