我在弄清楚如何为定义其他两种类型之间选择的 Enum 类型定义 FromJSON 实例时遇到了一些麻烦。我的预感是我对 、<*> 和 (.:) 运算符以及 Aeson Object 类型的工作原理没有充分的了解,但我无法解析编译器错误然而。(谢天谢地,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
]
这工作正常,但我一直无法为 FromJSON 定义一个实例ExampleChoice
:
data ExampleChoice = Choice1 Type1
| Choice2 Type2
deriving (Show,Typeable)
data ChoiceSelection =
ChoiceSelection
{ csValue :: ExampleChoice
} deriving (Show,Typeable)
instance FromJSON ExampleChoice where
parseJSON (Object x) = -- ???
parseJSON _ = mzero
instance ToJSON ExampleChoice where
toJSON (Choice1 t@(Type1 _)) = toJSON t
toJSON (Choice2 t@(Type2 _)) = toJSON t
我曾想过尝试将其定义为 msum,如下所示:
instance FromJSON ExampleChoice where
parseJSON (Object x) =
msum [ -- Some attempt at parsing Type1
, -- Some attempt at parsing Type2
, mzero
]
parseJSON _ = mzero
但是,我还没有弄清楚那个解析。
我还没有尝试使用 TemplateHaskell 和 derivedJSON 为我定义这个,但即使这不会导致问题,我很好奇如何解决这个问题。
编辑:deriveJSON 效果很好。不过,我仍然很好奇如何手动构建它。