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
相关产品推荐
相关产品推荐

