Servant.Swagger ToSchema for Data.Bson.ObjectId - PullRequest
       31

Servant.Swagger ToSchema for Data.Bson.ObjectId

0 голосов
/ 11 апреля 2020

Я пытаюсь построить Swagger spe c для моего проекта Servant.

Часть моего определения API содержит внутренние объекты модели, которые имеют _id поле типа Data.Bson.ObjectId

type API = rest
      :<|> "signup" :> ReqBody '[JSON] Credentials :> Post '[JSON] Account
      :<|> "signin" :> ReqBody '[JSON] Credentials :> Post '[JSON] Session

Так что мне нужно определить ToSchema для Account и Session чтобы избежать добавления дополнительных слоев, которые будут иметь, например, String поля вместо ObjectId.

data Account = Account
    { _id       :: ObjectId
    , user      :: User
    , createdAt :: UTCTime
    , updatedAt :: UTCTime
    } deriving (Generic, Typeable, Show, Read, Eq, Ord)

instance ToBSON Account
instance FromBSON Account

instance ToJSON Account where
    toJSON (Account oid user createdAt updatedAt) =
        object [ "_id"       .= show oid
               , "user"      .= toJSON user
               , "createdAt" .= iso8601Show createdAt
               , "updatedAt" .= iso8601Show updatedAt ]

instance FromJSON Account where
    parseJSON (Object o) =
        Account <$> o .: "_id"
                <*> o .: "user"
                <*> o .: "createdAt"
                <*> o .: "updatedAt"
instance ToSchema Account where
  declareNamedSchema proxy = genericDeclareNamedSchema defaultSchemaOptions proxy
    & mapped.schema.description ?~ "This is an example of a Account"
    & mapped.schema.example ?~ toJSON Model_Account.demo

instance ToSchema User where
  declareNamedSchema proxy = genericDeclareNamedSchema defaultSchemaOptions proxy
    & mapped.schema.description ?~ "This is an example of a User"
    & mapped.schema.example ?~ toJSON Model_User.demo

instance ToSchema Session where
  declareNamedSchema proxy = genericDeclareNamedSchema defaultSchemaOptions proxy
    & mapped.schema.description ?~ "This is an example of a Session"
    & mapped.schema.example ?~ toJSON Model_Session.demo

Я также должен реализовать ToSchema для ObjectId, и я не не понимаю, как это сделать.

instance ToSchema ObjectId where
  declareNamedSchema proxy = genericDeclareNamedSchema defaultSchemaOptions proxy
    & mapped.schema.description ?~ "This is an example of ObjectId"
    & mapped.schema.example ?~ "5e8da2d2393d8b1acd000001"

Я получаю следующую ошибку

Data.Swagger.Internal.Schema.genericDeclareNamedSchema
:: SchemaOptions
-> Proxy ObjectId -> Declare (Definitions Schema) NamedSchema
Defined in ‘Data.Swagger.Internal.Schema’

Server.hs:210:30: error:
    • Could not deduce: Data.Swagger.Internal.TypeShape.GenericHasSimpleShape
                          ObjectId
                          "genericDeclareNamedSchemaUnrestricted"
                          (Data.Swagger.Internal.TypeShape.GenericShape (Rep ObjectId))
        arising from a use of ‘genericDeclareNamedSchema’
    • In the first argument of ‘(&)’, namely
        ‘genericDeclareNamedSchema defaultSchemaOptions proxy’
      In the first argument of ‘(&)’, namely
        ‘genericDeclareNamedSchema defaultSchemaOptions proxy
           & mapped . schema . description
               ?~ "This is an example of ObjectId"’
      In the expression:
        genericDeclareNamedSchema defaultSchemaOptions proxy
          & mapped . schema . description ?~ "This is an example of ObjectId"
          & mapped . schema . example ?~ "5e8da2d2393d8b1acd000001"
Server.hs:210:30: error:
    • No instance for (Generic ObjectId)
        arising from a use of ‘genericDeclareNamedSchema’
    • In the first argument of ‘(&)’, namely
        ‘genericDeclareNamedSchema defaultSchemaOptions proxy’
      In the first argument of ‘(&)’, namely
        ‘genericDeclareNamedSchema defaultSchemaOptions proxy
           & mapped . schema . description
               ?~ "This is an example of ObjectId"’
      In the expression:
        genericDeclareNamedSchema defaultSchemaOptions proxy
          & mapped . schema . description ?~ "This is an example of ObjectId"
          & mapped . schema . example ?~ "5e8da2d2393d8b1acd000001"

Как добавить реализацию ToSchema для пользовательского типа, такого как ObjectId, который может быть легко преобразован в String, потому что он реализует show / read?

1 Ответ

3 голосов
/ 11 апреля 2020
• No instance for (Generic ObjectId)

Как следует из названия, genericDeclareNamedSchema работает только для типов данных, которые имеют экземпляр Generic. ObjectId не реализует его, поэтому единственный вариант - объявить схему полностью вручную, см., Например, документацию ToSchema.

...