aeson-schemas
aeson-schemas copied to clipboard
Break up `HasSchemaResult` to not require all constraints when only one is needed
Describe the bug
First of all, thanks for the amazing plugin 🙂 I just started picking up Haskell for my pet project so my knowledge is pretty limited. So to my understanding, this constraint https://github.com/LeapYear/aeson-schemas/blob/70fc7e2158c4dc2626cbc4ead5998bab126c3ac0/src/Data/Aeson/Schema/Internal.hs#L178 will make sure that every type used in the schema
QuasiQuote should always have both FromJSON
and ToJSON
instance. I think this can be a bit problematic if, for instance, I have a password type that can be parsed but shouldn't be sent over the wire:
data Hash = Plain | Hashed
newtype Password (hash :: Hash) = Password Text
mkPlainPassword :: Text -> Either Text (Password 'Plain)
mkPlainPassword pw
| T.length pw >= 8 = pure $ Password pw
| otherwise = Left "Password should be at least 8 chars"
instance FromJSON (Password 'Plain) where
parseJSON rawPw = do
pw <- parseJSON rawPw
case mkPlainPassword pw of
Right p -> pure p
Left e -> fail $ T.unpack e
type PasswordPlain = Password 'Plain
type PostNewUser =
Object
[schema|
{
username: Text,
email: Text,
password: PasswordPlain,
fullname: Text,
}
|]
At least as far as Servant is concerned, I got a type error saying that Password 'Plain
should have ToJSON
instance, while PostNewUser
is only consumed as a request body and not as a response.
data User = ...
instance ToJSON User where
toJSON u =
object
[ "username" .= user_username u
, "email" .= user_email u
, "fullname" .= user_fullname u
]
type SignUpAPI = ReqBody '[JSON] PostNewUser :> Post '[JSON] User
server :: Server SignupAPI
server = ...
-- | Error
--
-- No instance for (ToJSON (Password 'Plain)) arising from a use of `serve`
app = serve (Proxy @SignUpAPI) server
I'm not sure if this is Servant's specific problem or not, but perhaps you can help me give a clue
Expected behavior
I should be able to define a custom type without having ToJSON
instance.