Servant.Swagger Data.Bson.ObjectId 的 ToSchema

Servant.Swagger ToSchema for Data.Bson.ObjectId

我正在尝试为我的 Servant 项目构建 Swagger 规范。

我的 API 定义的一部分包含具有 _id 类型 Data.Bson.ObjectId

字段的内部模型对象
type API = rest
      :<|> "signup" :> ReqBody '[JSON] Credentials :> Post '[JSON] Account
      :<|> "signin" :> ReqBody '[JSON] Credentials :> Post '[JSON] Session

所以我需要为 AccountSession 定义 ToSchema 以避免添加额外的层,这些层将具有 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

我还必须为 ObjectId 实施 ToSchema,但我不知道该怎么做。

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"

我如何为像 ObjectId 这样的自定义类型添加 ToSchema 实现,它可以很容易地转换为 String,因为它实现了 show/read

• No instance for (Generic ObjectId)

顾名思义,genericDeclareNamedSchema 仅适用于具有 Generic. ObjectId does not implement it, so your only option is to declare the schema entirely by hand, see the documentation of ToSchema 实例的数据类型。