我如何摆脱某种类型?使用Data.Aeson进行JSON解析

时间:2012-01-24 23:35:05

标签: haskell

Haskell初学者在这里。我想用JSON传递一个“type”参数,并使用read解析为本机Haskell类型。以下作品:

data CreatureType = Bot | Player deriving (Generic, Typeable, Show, Read)
data Creature = Creature CreatureType deriving (Typeable, Show)

instance FromJSON Creature where
    parseJSON (A.Object v) = Creature <$> read <$> (v .: "type")  
    parseJSON _          = mzero

我想将其更改为与readMay一起使用,以便在读取失败时不会崩溃。我一直卡住了。如果mzero返回readMay,则parseJSON需要返回Nothing

主要问题:如何让这个函数使用readMay在读取失败时返回mzero

这是我尝试过的:

instance FromJSON Creature where
    parseJSON (A.Object v) = do
        let t = (v .: "type") :: Parser String
            mt = readMay <$> t :: Parser (Maybe CreatureType)
        -- ?? 
        -- guard -- I can't use this because it wants a Bool, and I only have Parser Bool
        -- Creature <$> read <$> mt
    parseJSON _          = mzero

mtParser (Maybe CreatureType)。如果是Nothing,我如何更改我返回的内容?我不能使用模式匹配,因为Data.Aeson似乎没有为Parser导出值构造函数。我似乎找不到任何方法可以在解析器中提供值,因此,是否有一个通用的haskell方法可以做到这一点?我看了Control.Applicative但找不到任何东西。以下是Data.Aeson的文档。 http://hackage.haskell.org/packages/archive/aeson/0.5.0.0/doc/html/Data-Aeson.html

1 个答案:

答案 0 :(得分:1)

不会在do-block工作中绑定值吗?

maybeCreature <- mt
case maybeCreature of
  Nothing -> mzero
  Just cr -> return (Creature cr)

或类似的?

instance FromJSON Creature where
    parseJSON (A.Object v) = do
        let t = (v .: "type") :: Parser String
            mt = readMay <$> t :: Parser (Maybe CreatureType)
        maybeCreature <- mt
        -- variant 1, guard
        guard (isJust maybeCreature)
        return (Creature $ fromJust maybeCreature)
        -- variant 2, fromMaybe
        fromMaybe mzero (return . Creature) maybeCreature
        -- variant 3, case, see above
    parseJSON _          = mzero