You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Scotty开发CRUD应用:Text与Key Todos类型匹配错误求助

解决Persistent中Text类型UUID无法匹配Key Todos的查询问题

报错核心是类型不匹配:你从请求参数拿到的id是Text类型,但TodosId字段对应的类型是Key Todos(Persistent的类型化主键),直接用Text和Key Todos比较会触发类型错误。以下是分场景的解决方案:


情况1:Todo实体主键是Text类型(存储UUID字符串)

如果你的Persistent实体定义将UUID以Text类型作为主键,比如:

share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
Todos
    id Text
    content Text
    completed Bool
    Primary id
    deriving Show Eq
|]

Persistent会自动生成TodosKey构造函数,用于将Text转换成Key Todos类型。修改getTodo函数如下:

getTodo :: ActionM ()
getTodo = do
  (id :: Text) <- param "id"
  let todoKey = TodosKey id  -- 转换Text为Key Todos
  -- 用get查询单个实体比selectList更符合语义
  maybeTodo <- liftIO $ inBackend $ get todoKey
  case maybeTodo of
    Nothing -> status status404 >> json ("Todo不存在" :: Text)
    Just todo -> json $ Entity todoKey todo

情况2:Todo实体主键是UUID类型

如果实体定义使用原生UUID类型作为主键(需要依赖uuid库):

import Data.UUID (UUID)

share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
Todos
    id UUID
    content Text
    completed Bool
    Primary id
    deriving Show Eq
|]

需要先将请求参数的Text解析为UUID,再构造Key:

import Data.UUID (UUID)
import qualified Data.UUID as UUID
import Data.Text (unpack)

getTodo :: ActionM ()
getTodo = do
  (idStr :: Text) <- param "id"
  case UUID.fromString $ unpack idStr of
    Nothing -> status status400 >> json ("UUID格式无效" :: Text)
    Just todoUuid -> do
      let todoKey = TodosKey todoUuid
      maybeTodo <- liftIO $ inBackend $ get todoKey
      case maybeTodo of
        Nothing -> status status404 >> json ("Todo不存在" :: Text)
        Just todo -> json $ Entity todoKey todo

额外优化点

  • 用get替代selectList:get专门用于根据主键查询单个实体,返回Maybe类型,比返回列表更符合查询单个Todo的语义。
  • 增加错误处理:针对无效UUID或不存在的Todo返回对应的HTTP状态码和提示信息,提升接口健壮性。

内容的提问来源于stack exchange,提问作者Aron

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 15:35:28