Json 使用Aeson(Haskell)解码枚举选择

Json 使用Aeson(Haskell)解码枚举选择,json,haskell,aeson,Json,Haskell,Aeson,我在弄清楚如何为定义其他两种类型选择的枚举类型定义FromJSON实例时遇到了一些问题。我的直觉是,我对and和(.:)运算符以及Aeson对象类型的工作原理没有足够的了解,但我还无法解析编译器错误。(谢天谢地,ToJSON实例非常简单。) 给定两个子数据类型,我可以定义如下实例: data ChoiceSelection = ChoiceSelection { csValue :: Type1 -- Type2 here also works fine } de

我在弄清楚如何为定义其他两种类型选择的枚举类型定义FromJSON实例时遇到了一些问题。我的直觉是,我对and和(.:)运算符以及Aeson对象类型的工作原理没有足够的了解,但我还无法解析编译器错误。(谢天谢地,ToJSON实例非常简单。)

给定两个子数据类型,我可以定义如下实例:

data ChoiceSelection =
   ChoiceSelection
      { csValue :: Type1  -- Type2 here also works fine
      } deriving (Show,Typeable)

data Type1 =
   Type1
      { t1Value :: Int
      } deriving (Show,Typeable)

data Type2 =
   Type2
      { t2Value :: Bool
      } deriving (Show,Typeable)

instance FromJSON ChoiceSelection where
   parseJSON (Object x) =   ChoiceSelection
                        <$> (x .: "csValue")
   parseJSON _          = mzero

instance FromJSON Type1 where
   parseJSON (Object x) =   Type1
                        <$> (x .: "t1Value")
   parseJSON _          = mzero

instance FromJSON Type2 where
   parseJSON (Object x) =   Type2
                        <$> (x .: "t2Value")
   parseJSON _          = mzero

instance ToJSON ChoiceSelection where
   toJSON (ChoiceSelection value) =
      object [ "csValue" .= value
             ]

instance ToJSON Type1 where
   toJSON (Type1 value) =
      object [ "t1Value" .= value
             ]

instance ToJSON Type2 where
   toJSON (Type2 value) =
      object [ "t2Value" .= value
             ]
我想尝试将其定义为msum,如下所示:

instance FromJSON ExampleChoice where
   parseJSON (Object x) =
      msum [ -- Some attempt at parsing Type1
           , -- Some attempt at parsing Type2
           , mzero
           ]
   parseJSON _          = mzero
但是,我还没有弄清楚解析的方法

我还没有尝试使用TemplateHaskell和deriveJSON来为我定义它,但即使这不会引起问题,我还是很好奇如何解决这个问题


编辑:deriveJSON非常有效。不过,我仍然很好奇如何手工构建它。

您需要将
更改为json
实例,这样您就可以确定要使用哪个数据构造函数(我还没有测试代码,但我希望这能为您提供一些想法):

import qualified Data.HashMap.Strict为H
实例ToJSON ExampleChoice在哪里
toJSON(choice1t@(Type1)))=object[“Choice1”。=t]
toJSON(choice2t@(Type2)))=object[“Choice2”。=t]
来自JSON ExampleChoice的实例
parseJSON(对象(H.toList->[(键,值)])
|key==“Choice1”=Choice1解析JSON值
|key==“Choice2”=Choice2解析JSON值
parseJSON=失败“”

您需要将
实例更改为json
实例,这样您就可以确定要使用哪个数据构造函数(我还没有测试代码,但我希望这能给您提供思路):

import qualified Data.HashMap.Strict为H
实例ToJSON ExampleChoice在哪里
toJSON(choice1t@(Type1)))=object[“Choice1”。=t]
toJSON(choice2t@(Type2)))=object[“Choice2”。=t]
来自JSON ExampleChoice的实例
parseJSON(对象(H.toList->[(键,值)])
|key==“Choice1”=Choice1解析JSON值
|key==“Choice2”=Choice2解析JSON值
parseJSON=失败“”

我最终使用msum方法实现了类似的功能。我意识到我的问题是对操作员的误解,现在我更理解这是fmap。我无法在这个注释中使用格式,但在一行中它看起来是这样的:parseJSON(Object x)=msum[Choice1 parseJSON x,Choice2 parseJSON x]此外,我注意到自动派生使JSON将ChoiceN元素包装在exampleCooice元素中,但这个解决方案很好地“隐藏”ExampleChoice功能显示在JSON中。我最终使用msum方法实现了类似的功能。我意识到我的问题是对操作员的误解,现在我更理解这是fmap。我无法在这个注释中使用格式,但在一行中它看起来是这样的:parseJSON(Object x)=msum[Choice1 parseJSON x,Choice2 parseJSON x]此外,我注意到自动派生使JSON将ChoiceN元素包装在exampleCooice元素中,但这个解决方案很好地“隐藏”ExampleChoice功能在JSON中显示。
instance FromJSON ExampleChoice where
   parseJSON (Object x) =
      msum [ -- Some attempt at parsing Type1
           , -- Some attempt at parsing Type2
           , mzero
           ]
   parseJSON _          = mzero
import qualified Data.HashMap.Strict as H

instance ToJSON ExampleChoice where
   toJSON (Choice1 t@(Type1 _)) = object ["Choice1" .= t]
   toJSON (Choice2 t@(Type2 _)) = object ["Choice2" .= t]


instance FromJSON ExampleChoice
    parseJSON (Object (H.toList -> [(key, value)]))
        | key == "Choice1"  = Choice1 <$> parseJSON value
        | key == "Choice2" = Choice2 <$> parseJSON value
    parseJSON _        = fail ""