2012-04-26 28 views
3

我见过ToJSON每个实例和FromJSON两种数据类型与单个构造函数,像这样:如何为具有多个构造函数的数据类型编写ToJSON/FromJSON实例?

data RewindConfig = RConfig JobID Phase 
         deriving Show 

instance FromJSON RewindConfig where 
    parseJSON (Object o) = RConfig 
    <$> o .: "JobID" 
    <*> o .: "Phase" 
    parseJSON _ = fail "invalid RewindConfig" 

我以为我会看埃宋是如何使与多个构造类型的实例,例如Either

instance (FromJSON a, FromJSON b) => FromJSON (Either a b) where 
    parseJSON (Object (H.toList -> [(key, value)])) 
     | key == left = Left <$> parseJSON value 
     | key == right = Right <$> parseJSON value 
    parseJSON _  = fail "" 

在parseJSON模式匹配混淆了我,我不明白是怎么回事(H.toList -> [(key, value)])

的数据类型我想使实例为如下所示:

data Foo = Bar String 
     | Baz String 
     | Bin String 

它确实发生了,以我做的东西我知道如何实现

data Foo = (Maybe Bar) (Maybe Baz) (Maybe Bin) 

,但似乎未能如愿。有人可以通过解释Either实例的情况来帮助我解决问题,并且可能会为Foo的收件人/发件人实例提供一些指导?

更新:我认为实例Aeson实现的Maybe更清晰,并告诉我需要知道我的需求。不过,我想知道Either是怎么回事。

回答

4

模式(Object (H.toList -> [(key, value)]))被称为view pattern。你可以把它读作这样的事:

parseJSon (Object o) = case H.toList o of 
    [(key, value)] 
     | key == left -> Left <$> parseJSON value 
     | key == right -> Right <$> parseJSON value 

它实际上是略有不同,流传至今的Object时,上面的总是会提交到模式Object o,而当双方的“Object o匹配的视图模式只会犯模式“并且”H.toList o匹配[(key, value)]模式“条件成立,但对于此示例无关紧要。

2

json软件包包含您可能要采用的数据类型的编码。 如果你只是得到Data你可以使用它。它不是非常快,但非常容易使用。

1

假设每个数据类型都有不同的重点,另一种方法可以使用的镜头 - 我喜欢它,因为它的简洁和可读性。例如,如果围绕A,B和C的所有包含FromJSON实例的包装:

import Data.Aeson 
import Data.Maybe 
import Data.Aeson.Lens 
import Control.Lens 

data Wrap = WrapA A | WrapB B | WrapC C 

instance FromJSON Wrap where 
    parseJSON json 
     | isJust (json ^? key "A's unique key") = WrapA <$> parseJSON json 
     | isJust (json ^? key "B's unique key") = WrapB <$> parseJSON json 
     | isJust (json ^? key "C's unique key") = WrapC <$> parseJSON json 
     | otherwise = fail "Bad message" 
+1

谢谢!我很欣赏从这篇旧文章中学到新东西 – 2014-09-04 23:03:30

相关问题