使用Yesod验证JSON请求的最佳实践

时间:2014-05-25 09:00:13

标签: json rest haskell yesod

我正在使用Yesod编写JSON RESTFul服务,需要实现请求验证。 因为服务接受JSON,我不能使用Yesod.Form。我喜欢scalaz validation使用的方式,但我在Haskell中找不到这样的方法。

是否有最佳实践可以实现验证,以便回答结构化错误消息,如下所示:

请求

{
    "birthDate": "2017.07.14",
    "count": "three",
    "kind": "baz",
    "entity": {
        "id": -1
    }
}

响应

{
    "errors": {
        "birthDate": "Date should be less than 2014.05.25", // current date
        "count": "should be a number",
        "kind": "must be one of [foo, bar]",
        "entity": {
            "id": "Entity with id -1 not found"
        }
    }
}

2 个答案:

答案 0 :(得分:7)

我建议使用aeson的本机解析功能,这将同时解析传入的JSON并将其转换为Haskell数据结构。

答案 1 :(得分:5)

有一个digestive-functors-aeson库利用Text.Digestive.Form并允许编写表达式验证规则。以下是tests

的要点
pokeForm :: Monad m => Form Text m Pokemon
pokeForm = Pokemon <$> "name" .: nonEmptyText
                   <*> "number" .: parseInteger
  where
    nonEmptyText = check "Name cannot be empty" (not . T.null) $
                     text Nothing

testPokedexFailHead =
    let (v, r) = runIdentity $ digestJSON pokedexForm json
    in testGroup "Submit pokedex with a single invalid item"
         [ testCase "Failed validation" $ r @?= Nothing
         , testCase "jsonErrors shows correct errors" $ jsonErrors v @?= errors
         ]
  where
    (Just json) = decode "{\"pokemon\":[{\"name\":\"\"}]}"
    (Just errors) = decode "{\"pokemon\":[{\"name\":\"Name cannot be empty\"}]}"

正如您所看到的,该库可以生成非常详细的错误,这些错误标记为验证失败的字段名称。