【问题标题】:Haskell, Aeson - how to debug instances?Haskell,Aeson - 如何调试实例?
【发布时间】:2012-09-13 12:30:15
【问题描述】:

我有一个复杂的嵌套 json,我正在尝试使用 Aeson 和 Attoparsec 将其解析为我的自定义类型。基于来自问题的信息:Haskell, Aeson & JSON parsing into custom typeAeson: How to convert Value into custom type? 以及来自互联网的一些信息。

当我使用以下代码时,我从重叠的 FromJSON 实例中获取“无”值,但代码肯定会通过每个实例,我已经通过禁用其他一些实例来测试这一点。那么主要问题:如何在实例中测试代码并查看 GHCi 中数据在执行过程中如何变化?

P.S:尝试设置断点和“跟踪”,但它们仅在 main 和 parseCfg 函数中有效。

{-# LANGUAGE OverloadedStrings, FlexibleInstances #-}

-- high level data
data Cfg = Cfg { nm  :: CProperty,
             author :: CProperty,
             langs :: CValue,
             grops :: CListArr,
             projs :: CPropArr
           } deriving (Show)

...

instance FromJSON CProperty where
parseJSON _          = mzero
parseJSON (Object o) = CProperty <$> toCProperty o
  where
    toCProperty :: (HM.HashMap T.Text Value) -> J.Parser (T.Text, T.Text)
    toCProperty _  = error "unexpected property"
    toCProperty o' = do
      l <- return $ HM.toList o'
      k <- return $ fst $ head l
      v <- return $ snd $ head l
      v' <- parseJSON v
      return $ (k, v')

... lot's of different instances

-- |this instance is specific for different files
-- based on common functions to work with most of nested json code
instance FromJSON Cfg where
  parseJSON _          = mzero
  parseJSON (Object o) = do
    nm     <- (parseJSON :: Value -> J.Parser CProperty) =<< (o .: T.pack "Name")
    autor  <- (parseJSON :: Value -> J.Parser CValue)    =<< (o .: T.pack "Author")
    langs  <- (parseJSON :: Value -> J.Parser CProperty) =<< (o .: T.pack "Languages")
    groups <- (parseJSON :: Value -> J.Parser CListArr)  =<< (o .: T.pack "Groups")
    projs  <- (parseJSON :: Value -> J.Parser CPropArr)  =<< (o .: T.pack "Projects")
    return $ Cfg nm author langs groups projs
------------------------------------------------------------------------------------

main :: IO ()
main = do:
  s <- L.readFile "/home/config.json"
  -- print $ show s
  let cfg =  parseCfg s
  print $ show $ cfg

parseCfg :: L.ByteString -> Maybe Cfg
parseCfg s = decode s

【问题讨论】:

    标签: json parsing haskell aeson


    【解决方案1】:

    明显的问题是在

    instance FromJSON CProperty where
        parseJSON _          = mzero
        parseJSON (Object o) = ...
    

    第一个子句匹配所有输入,因此无论参数是什么,您的实例都会返回 mzero。您应该更改子句的顺序。

    编译时出现警告,GHC 会告诉您重叠模式。

    【讨论】:

    • 是的,这很有帮助,现在使用断点。后续问题:有什么方法可以首先处理错误和无用的值? (实际上,这就是我写这样的代码的原因)
    • 有一些方法可以处理无用的值(和错误,但可能仅在 IO 中,取决于“错误”的含义),但要获得有意义的建议,您应该更具体。什么是错误/无用值,如何指示/检测它们,以及您想在哪里处理它们。这可能是一个新问题。
    • 好的,谢谢。当我有更具体的问题时,我会创建一个新的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多