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

时间:2015-08-16 01:02:19

标签: 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实例来解析整个响应并检查填写的记录。这有点单调乏味。

有关库代码中的内容导致此问题的任何建议吗?以及如何解决它?

谢谢,

1 个答案:

答案 0 :(得分:3)

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

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

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

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

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