haskell - Aeson 或 Wai.JSON QuasiQuoter 的问题 -- 将 0.0 转换为 0

标签 haskell aeson hspec

我正在使用 Test.Hspec.Wai.JSON 来检查我的 api 端点的返回值。我注意到,每当我创建一个值为 0.0 的 json 时,当测试运行时,它会将其转换为 0 (Int),并且如果 api 返回 0.0 ,测试失败。

let  j = [json|{"test":0.0}|]
request "GET" "some_url" [("Content-Type", "application/json")] ""
        `shouldRespondWith` j {matchStatus = 200}

   body mismatch:
     expected: {"test":0}  ---> this is the issue (0.0 has become 0)
     but got:  {"test":0.0} 

我对 Haskell 的了解还不够深入,无法找出库代码中发生这种情况的位置。我查看了 Test.Hspec.Wai.JSON 的源代码,它似乎依赖于 Aeson.QQ 所以不太确定问题的根源。这是Test.Hspec.Wai.JSON source这是Aeson.QQ Source

因此,我的解决方法是编写一个 FromJSON 实例来解析整个响应并检查填写的记录。这有点乏味。

关于库代码中的原因有什么建议吗?又该如何解决呢?

谢谢

最佳答案

嫌疑人似乎是Data.Aeson.QQ的这一行:

toExp (JsonNumber n) = [|Number (fromRational $(return $ LitE $ RationalL (toRational n)))|]

它将数字转换为Rational,再将其转换为Haskell 表达式,然后将结果表达式转换回Number。这最终会丢弃它是 0.0 而不是 0 的事实。

这通常不会成为问题,因为 Aeson 正确定义了 == 以使具有相同值的 Number 相等。这成为 Test.Hspec.Wai.JSON 的一个实际问题;它的工作方式是将对象编码回 ByteString 并期望它完全匹配。

虽然Data.Aeson.QQ是您问题的根本原因,但我不会责怪它。相反,Test.Hspec.Wai.JSON 不应该序列化 JSON 对象并期望它们的表示是等效的。相反,它应该反序列化实际响应并比较解码的对象是否相等。 (毕竟,浮点/整数不是唯一可能的问题。它也无法处理重新排序的对象键。)我不熟悉 Hspec,所以我不确定你会如何处理让它这样做。

关于haskell - Aeson 或 Wai.JSON QuasiQuoter 的问题 -- 将 0.0 转换为 0,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32030881/

相关文章:

Haskell:如何从标准输入中逐行读取值并将它们添加到 map 中?

haskell - Haskell printf 是如何工作的?

haskell - Haskell单例:排版包

haskell - 将新字段添加到带有 "lens"的 JSON 对象

json - Haskell Data.Decimal 作为 Aeson 类型

haskell - Hspec:如何抑制成功的测试结果

windows - 如何在 ghci 中使用数学符号(函数名)?

json - 如何使用 aeson 将数组解析为元组?

haskell - HSpec(或 HUnit)是否有可能将更多信息附加到打印的断言中,并且仅在失败的情况下?

haskell - 使用 HSpec 和 QuickCheck 验证 Data.Monoid 属性