Yesod Persist:如何从JSON生成String类型PageId并更新Link模型
解决Yesod中从Text生成PageId并更新Link字段的问题
首先得理清楚你的场景:你的Page模型用UUID作为主键,所以PageId(也就是Persistent生成的Key Page类型)本质就是UUID类型,而非默认的Int64。前端传过来的是Text格式的UUID字符串,你需要把它转换成PageId才能更新Link的pageId字段,同时还要处理解析失败的情况——另外你的处理器还有个小问题:update返回的是更新行数而非记录本身,得调整下。
步骤1:调整ApiLink定义(两种可选方案)
你可以选择让ApiLink直接接收Text格式的UUID字符串,或者直接用UUID类型(后者更推荐,让Aeson自动处理解析逻辑):
方案一:接收Text后续手动解析
data ApiLink = ApiLink { linkPageId :: Text } deriving (Generic) instance FromJSON ApiLink
方案二:直接接收UUID类型
需要先导入相关包(记得在cabal依赖中添加uuid-types和aeson):
import Data.UUID (UUID) import Data.Aeson (FromJSON(..)) data ApiLink = ApiLink { linkPageId :: UUID } deriving (Generic) instance FromJSON ApiLink -- UUID的FromJSON实例已由uuid-types包提供,Generic可直接推导
步骤2:修正处理器代码
不管用哪种ApiLink定义,核心是把输入转换成PageId(即UUID),同时处理解析错误,还要正确获取更新后的记录:
import Data.UUID (fromText) import Yesod.Core (sendStatusJSON, status400) import Yesod.Persist (runDB, update, get404) import Data.Aeson (object, (.=)) patchApiLinkR :: LinkId -> Handler Value patchApiLinkR linkId = do -- 若用方案一(接收Text): ApiLink pageIdText <- requireJsonBody :: Handler ApiLink case fromText pageIdText of Just pageId -> processUpdate pageId Nothing -> sendStatusJSON status400 $ object ["error" .= ("Invalid UUID format" :: Text)] -- 若用方案二(直接接收UUID): -- ApiLink pageId <- requireJsonBody :: Handler ApiLink -- processUpdate pageId where processUpdate pageId = do -- 更新Link的pageId字段,注意pageId是Maybe类型,需包裹Just _ <- runDB $ update linkId [LinkPageId =. Just pageId] -- 获取更新后的Link记录返回给前端 updatedLink <- runDB $ get404 linkId returnJson updatedLink
关键说明
- PageId的本质:因为你给Page模型指定了
Primary uuid,Persistent会将PageId(即Key Page)的类型设置为UUID,和你定义的uuid字段类型一致,而非默认的Int64。 - UUID解析逻辑:如果前端传的是字符串格式的UUID,用
fromText可以将Text转换成UUID,解析失败时返回400错误提示格式无效。 - update的返回值:Persistent的
update函数返回的是被更新的行数,不是更新后的记录,所以需要用get404去数据库拉取最新的Link对象再返回。
内容的提问来源于stack exchange,提问作者Alebon
相关产品推荐
相关产品推荐

