We’ve started playing around with the rest set of libraries at work. Some of the nice things rest does:
Routes with built in versioning
Automatic documentation and example generation
Generation of Ruby, Haskell and JavaScript client libraries (and probably Python and Scala additions from us, soon)
I was originally skeptical because most of the examples rely on GHC Generics and Data.Typeable which I find to be anti-modular. Luckily you can remove most of the generic programming parts and create your instances in the usual ways.
Here’s an example from our code:
data AccountError = InvalidAccountNumber String
| EmptyPremiseId
| EmptyServicePointId
deriving (Show, Typeable)
instance S.JSONSchema AccountError where
schema _ =
S.Choice [
S.Object [
S.Field "tag" True (S.Constant (String "invalid_account_number")),
S.Field "account_number" True (S.Value S.unboundedLength)
],
S.Object [
S.Field "tag" True (S.Constant (String "empty_service_point_id"))
],
S.Object [
S.Field "tag" True (S.Constant (String "empty_premise_id"))
]
]
parseAccountError :: Object -> Parser AccountError
parseAccountError o = do
tag <- o .: "tag"
case (tag :: String) of
"invalid_account_number" -> InvalidAccountNumber <$> o .: "account_number"
"empty_premise_id" -> pure EmptyPremiseId
"empty_service_point_id" -> pure EmptyServicePointId
s -> fail $ "Unkown tag " ++ show s
instance FromJSON AccountError where
parseJSON = withObject "AccountError" parseAccountError
instance ToJSON AccountError where
toJSON (InvalidAccountNumber s) = object [("tag", "invalid_account_number"), ("account_number", fromString s)]
toJSON EmptyPremiseId = object [("tag", "empty_premise_id")]
toJSON EmptyServicePointId = object [("tag", "empty_service_point_id")]
accountErrorCreate :: Handler (ReaderT KafkaConfig IO)
accountErrorCreate = mkInputHandler (jsonI . someI) $ lift . sendAccountError
I want to try and unify the schema, parsing and pretty-printing code. Not sure if I’ll be able to do it, though.
We’ve started playing around with the rest set of libraries at work. Some of the nice things rest does:
I was originally skeptical because most of the examples rely on GHC Generics and Data.Typeable which I find to be anti-modular. Luckily you can remove most of the generic programming parts and create your instances in the usual ways.
Here’s an example from our code:
I want to try and unify the schema, parsing and pretty-printing code. Not sure if I’ll be able to do it, though.