From 7f9323be0f112f7e5d51c9a5a41cf436e0023d20 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Hamal=20Dvo=C5=99=C3=A1k?= <mordae@anilinux.org>
Date: Sat, 15 May 2021 22:41:28 +0200
Subject: [PATCH] Support parsing JSON values out-of-the-box
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Jan Hamal Dvořák <mordae@anilinux.org>
---
 lib/Hikaru/Action.hs | 19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/lib/Hikaru/Action.hs b/lib/Hikaru/Action.hs
index 3e496cb..c5e4b14 100644
--- a/lib/Hikaru/Action.hs
+++ b/lib/Hikaru/Action.hs
@@ -123,7 +123,7 @@ where
 
   import Control.Exception (throwIO, bracket_)
   import Control.Monad.Trans.Resource
-  import Data.Aeson (Value, ToJSON, encode, eitherDecode')
+  import Data.Aeson
   import Data.Binary.Builder
   import Data.Dynamic
   import Data.List (lookup, deleteBy)
@@ -602,14 +602,17 @@ where
   -- * Throws 'InternalError' is the body has already been consumed
   --   and was not cached as JSON.
   --
-  getJSON :: (MonadAction m) => m Value
+  getJSON :: (MonadAction m, FromJSON a) => m a
   getJSON = do
     -- First check out our stash.
     cache <- getActionField aeBody
 
     case cache of
       -- This is ideal, we already have what we need.
-      BodyJSON value -> return value
+      BodyJSON value ->
+        case fromJSON value of
+          Data.Aeson.Error err -> throwError BadRequest (cs err)
+          Data.Aeson.Success out -> return out
 
       -- Body has not been parsed yet. This is very good.
       BodyUnparsed -> do
@@ -630,7 +633,11 @@ where
 
         -- Cache and return.
         setActionField aeBody (BodyJSON value)
-        return value
+
+        -- Parse to the output type.
+        case fromJSON value of
+          Data.Aeson.Error err -> throwError BadRequest (cs err)
+          Data.Aeson.Success out -> return out
 
       -- Now this is bad. We have already read the body,
       -- but not as a JSON. This is an internal error.
@@ -927,9 +934,9 @@ where
   -- body to the result of encoding provided Aeson value.
   --
   sendJSON :: (MonadAction m, ToJSON a) => a -> m ()
-  sendJSON json = do
+  sendJSON payload = do
     defaultHeader hContentType "application/json"
-    setResponseBS (encode json)
+    setResponseBS (encode payload)
 
 
   -- |
-- 
GitLab