haskell - 带有仆人的数据库支持的 REST API?

标签 haskell servant postgresql-simple

我在设置简单的概念服务 API 证明时遇到问题。这是我的用户数据类型和我的 API 类型:

data User = User { id :: Int, first_name :: String, last_name :: String } deriving (Eq, Show, Generic)
instance FromRow User
instance ToRow User
$(deriveJSON defaultOptions ''User)

type API = "users" :> ReqBody '[JSON] User :> Post '[JSON] User

此处理程序方法使用 postgresql-simple,如下所示:
create u = liftIO $ head <$> returning connection "insert into users (first_name, last_name) values (?,?) returning id" [(first_name u, last_name u)]

样板代码,例如连接到数据库和路由方法已被省略。
问题是,如果我发出 POST 请求,我想做的是创建一个新用户,因此我将提供 JSON:
{ "first_name": "jeff", "last_name": "lebowski" }

但是我的程序在运行时失败了
Error in $: When parsing the record User of type Lib.User the key id was not present. 

这是有道理的,因为 API 指定了一个具有 id 字段的用户。但我不想在请求中传递一个虚假的 id(因为它们是由 postgres 按顺序分配的),因为这很糟糕。我也无法将 id 字段移出 User 数据类型,因为在向不同端点发出 GET 请求时 postgres-simple 由于模型数据库不匹配而失败(这很明显:通过 id 获取。未包括在上面)。
我在这里做什么?编写自定义 FromJson 实例?我已经尝试将 Data.Aeson.TH 选项标志 omitNothingFields 设置为 True 并将 id 字段设置为 Maybe Int,但这也不起作用。
任何意见,将不胜感激。

最佳答案

首先你要明白一个User和这个User对应的表中的一行是两个不同的东西。

一行有一个 id,用户没有。例如,您可以想象在不处理 id 或保存与否的情况下比较两个用户。

一旦被说服,您将不得不向类型系统解释这一点,或者您将不得不处理 Maybe 字段,我认为这不是这里的解决方案。

有人讲了Template Haskell,我觉得这里说的有点过头了,需要先解决问题。

您可以做的是使用数据类型来表示数据库中保存的行。我们称之为实体。

newtype PrimaryKey = PrimaryKey Int

data Entity b = Entity PrimaryKey b

然后在数据库中保存用户行的函数可能需要 user作为参数并返回 PrimaryKey (当然,在你的数据库 monad 中)。
从数据库读取的其他函数将使用 Entity User 返回一些内容。

您的字段声明不会重复,因为您将 User 类型重用为参数。

您必须相应地调整 FromRow/ToRow 和 FromJSON/ToJSON。

关于haskell - 带有仆人的数据库支持的 REST API?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38818478/

相关文章:

haskell - 从 TemplateHaskell 中的文件中读取模块

haskell - 哪个 Haskell 编译器具有信息丰富的(初学者友好的)错误消息?

sqlite - Haskell、Sqlite、池和仆人

haskell - 如何为 Elm post 请求指定正文媒体类型?

postgresql - count(*) 类型与 Database.PostgreSQL.Simple 的兼容性错误?

函数上的 PostgreSQL-simple `execute` 失败并显示 "execute resulted in Col 1-column result"

haskell - 具有两个以上选项的 Tuple 或 Either 的相反名称是什么?

haskell - Haskell中的尾递归二项式系数函数

haskell - 如何在自定义servant处理程序中响应HTTP状态?

postgresql - Haskell PostgreSQL 简单 FromField