Ошибки синтаксического анализа JSON в Haskell Servant - PullRequest
0 голосов
/ 31 мая 2018

С учетом следующего сервера Servant:

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeOperators #-}

module ServantSample (main) where

import Data.Aeson
import Data.Aeson.TH
import Network.Wai
import Network.Wai.Handler.Warp
import Servant

data Spec = Spec
  { schema :: Object
  } deriving (Eq, Show)
$(deriveJSON defaultOptions ''Spec)

type Api = ReqBody '[JSON] Spec :> Post '[JSON] NoContent

server :: Server Api
server = postDoc

postDoc :: Spec -> Handler NoContent
postDoc _ = return NoContent

api :: Proxy Api
api = Proxy

app :: Application
app = serve api server

main :: IO ()
main = run 8080 app

... и следующего скручивания к работающему экземпляру вышеуказанного сервера:

curl localhost:8080 -H 'Content-Type: application/json' --data '{"schema": "I am not an object but I should be!"}'

Я получаю обратно:

Error in $.schema: expected HashMap ~Text v, encountered String

Есть ли способ перехватить ошибку Aeson и заменить ее чем-то, что не передает клиенту детали реализации?Насколько я могу судить, все это происходит за кулисами в механизме Слуги, и я не могу найти никакой документации о том, как подключиться к нему.

Например, я хотел бы вернуть что-то вроде:

Expected a JSON Object under the key "schema", but got the String "I am not an object but I should be!"

Спасибо!

1 Ответ

0 голосов
/ 31 мая 2018

Написание экземпляра FromJSON вручную решает, по крайней мере, половину вашей проблемы.

instance FromJSON Spec where
  parseJSON (Object o) = do
    schema <- o .: "schema"
    case schema of
      (Object s) -> pure $ Spec s
      (String s) -> fail $ "Expected a JSON Object under the key \"schema\", but got the String \"" ++ unpack s ++ "\"\n"
      _          -> fail $ "Expected a JSON Object under the key \"schema\", but got the other type"
  parseJSON wat = typeMismatch "Spec" wat

Затем ваша команда curl возвращает:

Error in $: Expected a JSON Object under the key "schema", but got the String "I am not an object but I should be!"

Очевидно, вы можете проверить различные Value наберите конструкторы из Aeson и выделите их в отдельную функцию.

Получил код из рассмотрения реализации Data.Aeson.Types.typeMismatch

...