处理 Yesod 中的 JSON 个帖子
Handling JSON posts in Yesod
AngularJS 客户端正在向 Yesod 服务器发送 JSON post 以更新个人记录。 post 可以包含以下字段,每个字段都是可选的 - 客户端可以发送这些字段的任何子集:
- 名字
- 姓氏
- ...
- 活跃
为了稍微限制讨论,让我们假设客户端此刻只想切换 activity,因此它只会发送活动值(它特别希望保持其余部分不变)和消息将是:
{
active: 0
}
现在在服务器上,我们从URL(例如/api/v1.0/person/1)知道了这个人的id,但是客户端没有发送一个完整的人实体,所以通常:
person <- requireJsonBody :: Handler Person
_ <- runDB $ update personId ...
在这里不起作用。似乎需要一种更灵活的方法。也许是这样的:
mapToUpdate :: PersonInfo -> [Update PersonInfo]
其中 PersonInfo 是 FromJSON
的实例,定义为与 Person 匹配,但具有 Maybe a
类型的所有字段。然而,这似乎与 DRY 完全相反。
总结一下:如何处理 Yesod 中的这种用例并再次假设客户端可以发送一个人字段的任何子集?
你可以想象更可怕的场景。例如,一个 JSON post 需要映射到多个数据库实体的更新(api 实体不必映射 1:1 到数据库实体)。
我从来没有尝试过这个,但这是一个理论上的方法:
- 从数据库中抓取当前值
- 通过调用
toJSON
将该值序列化为 aeson Value
- 编写某种 "update" 算法,将两个
Value
合并在一起,例如mergeValues :: Value -> Value -> Value
- 将原始实体与用户上传的值合并
- 尝试用
parseJSON
解析结果值
- 如果成功,使用
replace
将其放回数据库
AngularJS 客户端正在向 Yesod 服务器发送 JSON post 以更新个人记录。 post 可以包含以下字段,每个字段都是可选的 - 客户端可以发送这些字段的任何子集:
- 名字
- 姓氏
- ...
- 活跃
为了稍微限制讨论,让我们假设客户端此刻只想切换 activity,因此它只会发送活动值(它特别希望保持其余部分不变)和消息将是:
{
active: 0
}
现在在服务器上,我们从URL(例如/api/v1.0/person/1)知道了这个人的id,但是客户端没有发送一个完整的人实体,所以通常:
person <- requireJsonBody :: Handler Person
_ <- runDB $ update personId ...
在这里不起作用。似乎需要一种更灵活的方法。也许是这样的:
mapToUpdate :: PersonInfo -> [Update PersonInfo]
其中 PersonInfo 是 FromJSON
的实例,定义为与 Person 匹配,但具有 Maybe a
类型的所有字段。然而,这似乎与 DRY 完全相反。
总结一下:如何处理 Yesod 中的这种用例并再次假设客户端可以发送一个人字段的任何子集?
你可以想象更可怕的场景。例如,一个 JSON post 需要映射到多个数据库实体的更新(api 实体不必映射 1:1 到数据库实体)。
我从来没有尝试过这个,但这是一个理论上的方法:
- 从数据库中抓取当前值
- 通过调用
toJSON
将该值序列化为 aeson - 编写某种 "update" 算法,将两个
Value
合并在一起,例如mergeValues :: Value -> Value -> Value
- 将原始实体与用户上传的值合并
- 尝试用
parseJSON
解析结果值
- 如果成功,使用
replace
将其放回数据库
Value