我有一个ajax调用将json发送到Yesod中的路由,我希望路由解析json并将其直接插入数据库。在我的模型文件中我有
createtime UTCTime default=now()
因为客户端没有向下发送创建时间而阻止解析json。我尝试为日志条目编写自己的parseJson,但由于getCurrentTime在IO monad中返回一个值,因此我无法插入UTCTime默认值。如果可能,我希望数据库设置值。
此时我唯一能想到的是创建类似LogEntryWithoutTime的类型,将JSON解析为该类并转换为LogEntry。有更简单的方法吗?
修改 我展示了三个不同的失败,将getCurrentTime添加到JSON解析中。首先,目的是解析createtime(如果可用),并默认为服务器上的getCurrentTime。这无论如何都是对的,因为我们不应该依赖客户的时间。
instance FromJSON Log where
parseJSON (Object o) = Log
<$> o .: "userid"
...
<*> o .:? "createtime" .!= liftIO getCurrentTime
错误是
Model.hs:58:32:
Couldn't match expected type ‘UTCTime’
with actual type ‘m0 UTCTime’
In the second argument of ‘(.!=)’, namely ‘liftIO getCurrentTime’
In the second argument of ‘(<*>)’, namely
‘o .:? "createtime" .!= liftIO getCurrentTime’
其次,我试着获取当前时间。
<*> liftIO getCurrentTime
我收到了错误
Model.hs:58:9:
No instance for (MonadIO
aeson-0.7.0.6:Data.Aeson.Types.Internal.Parser)
arising from a use of ‘liftIO’
In the second argument of ‘(<*>)’, namely ‘liftIO getCurrentTime’
如果我将行更改为
<*> getCurrentTime
然后我得到
Model.hs:58:9:
Couldn't match type ‘IO’
with ‘aeson-0.7.0.6:Data.Aeson.Types.Internal.Parser’
Expected type: aeson-0.7.0.6:Data.Aeson.Types.Internal.Parser
UTCTime
Actual type: IO UTCTime
答案 0 :(得分:1)
在模型中定义default
属性的事情是,在持久化实体时仍需要定义所有值。据我所知,默认值仅适用于自动迁移和模式定义。
尝试从IO monad中提取getCurrentTime
(使用liftIO
)。
答案 1 :(得分:0)
我现在面临着同样的问题。我目前的想法是,由于我不希望用户向我提供完整的记录,因此我不应该以这种方式对其进行建模。相反,我应该模拟我期望从用户那里获得的请求主体,并将其转换为存储空间。
所以,你可能有PartialLog
的概念,它只有你希望用户发送的字段:
data PartialLog = PartialLog { partialLogMessage :: Text }
然后你可能有一个填补空白的功能并为你提供完整的记录:
{-# LANGUAGE RecordWildCards #-}
logFromPartial :: PartialLog -> UserId -> IO Log
logFromPartial p u = do
let logUserId = u
logMessage = partialLogMessage p
logCreatetime <- liftIO getCurrentTime
return Log{..}
n.b。我正在传递UserId
,因为我们可能希望该值来自经过身份验证的会话;用户无需告诉我们他们的ID是什么。