Best practice for checking JSON requests with Yesod

I am writing a JSON RESTFul service with Yesod and need to validate requests. I can not use Yesod.Form for it because the service accepts JSON. I like the validation method, but I havenโ€™t found such an approach in Haskell.

Is there a best practice for checking that would allow you to respond to messages with structured errors, for example:

Request

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

Answer

 { "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" } } } 
+7
json rest haskell yesod
source share
2 answers

There is a digestive-functors-aeson library that uses Text.Digestive.Form and allows you to write expressive validation rules. Here is the gist of 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\"}]}" 

As you can see, the library can create quite detailed errors that are marked with the names of the fields that did not pass the test.

+3
source share

I would recommend using aeson's own parsing capabilities to do this, which will simultaneously parse the incoming JSON and convert it to a Haskell data structure.

+7
source share

All Articles