【问题标题】:How to correctly error out in JSON parsing with Data.Aeson如何在使用 Data.Aeson 解析 JSON 时正确出错
【发布时间】:2015-04-14 04:14:34
【问题描述】:

我的类型和对应的 FromJSON 实现如下所示。

nonEmptyList 转换为Maybe NonEmpty,我正在尝试正确处理List 确实为空并且我必须中止解析的情况。这个解析实际上是在parseJsonBody 内部完成的,这意味着我不想通过error "foo" 摆脱它,但我想返回mzero(或者其他任何可以解决问题的方法,mzero 是到目前为止我偶然发现的唯一一件事)以便处理程序正确返回 400 而不是以 500 崩溃。

下面的方法可以编译,但据我所知,它几乎等于error 或在 parseJSON 中抛出的其他形式的异常。但是,如果我返回 mzero(例如,使用 <*> mzero 而不是该行),它会按预期失败。

import qualified Data.List.NonEmpty as NE
data GSAnswer = GSAnswer { gsAnswerQuestionId :: Int
                         , gsAnswerResponses :: NE.NonEmpty GSResponse
                         } deriving (Show, Eq)


instance FromJSON GSAnswer where
  parseJSON (Object o) =
    GSAnswer <$> o .: "question-id"
             -- how do I return mzero here based on NE.nonEmpty?
             -- this will throw an exception right now on an empty list
             <*> fmap (fromMaybe (fail "foo") . NE.nonEmpty) (o .: "responses")
  parseJSON _ = mzero

一种选择是以某种方式对fmap NE.nonEmpty (o .: "responses") 的结果进行模式匹配,但我无法完全弄清楚该模式会是什么:Parser 似乎没有任何构造函数?

【问题讨论】:

    标签: parsing haskell monads applicative aeson


    【解决方案1】:

    本质上,你需要一个Parser [a] -&gt; Parser NE.NonEmpty 转换器,这比较简单:

    -- toNonEmptyP :: Parser [a] -> Parser NE.NonEmtpy
    toNonEmptyP p = fmap NE.nonEmpty p >>= maybe mzero return
    

    我们将NE.nonEmpty 映射到我们的常规列表解析器上,从而得到Parser (Maybe NE.NonEmpty)。然后,我们使用maybe 检查Maybe,如果它是Nothing,则使用mzero,或者使用return,将解析后的值返回到解析上下文。然后您的 FromJSON 实例归结为

    instance FromJSON GSAnswer where
      parseJSON (Object o) =
        GSAnswer <$> o .: "question-id"
                 <*> toNonEmptyP (o .: "responses")
      parseJSON _ = mzero
    

    您可以使用fail msg 而不是mzero 来提供自定义错误消息,因为fail :: String -&gt; Parser a 不会触底。

    【讨论】:

    • 似乎可以解决问题,谢谢。有关如何将特定错误消息添加到解析器故障的任何建议?现在报告的错误消息是“mzero”,如果我可以在那里传递我自己的错误消息来解释为什么 Parser 必须中止,那就太好了。
    • 您是否尝试过在变压器中使用fail "msg" 而不是mzero?我目前不在我的电脑前,但我可以稍后查看。
    • 这似乎可以解决问题,谢谢,我将上面的内容更改为:toNonEmptyP :: String -> Parser [a] -> Parser (NE.NonEmpty a) toNonEmptyP msg p = fmap NE. nonEmpty p >>=可能(失败消息)返回
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-09
    • 2012-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多