Haskell 将嵌套属性添加到返回的记录
我有一个Yesod路由处理程序,它返回带有对象的JSONHaskell 将嵌套属性添加到返回的记录,haskell,yesod,Haskell,Yesod,我有一个Yesod路由处理程序,它返回带有对象的JSON { id: 1, title: "foo" content: "bar" } 我想添加一个带有元数据的\u links属性,该属性在实体本身中不存在,例如 { id: 1, title: "foo" content: "bar" _links: {self: http://localhost:3000/events/1} } 如何将\u链接添加到现有实体记录?这是我的处理程序: getEventR :: Event
{ id: 1,
title: "foo"
content: "bar"
}
我想添加一个带有元数据的\u links
属性,该属性在实体本身中不存在,例如
{ id: 1,
title: "foo"
content: "bar"
_links: {self: http://localhost:3000/events/1}
}
如何将\u链接
添加到现有实体记录?这是我的处理程序:
getEventR :: EventId -> Handler Value
getEventR eid = do
event <- runDB $ get404 eid
render <- getUrlRender
let renderedUrl = render $ EventR eid
let links = object
[ "self" .= renderedUrl
]
let returnVal = object
[ "data" .= (Entity eid event)
, "_links" .= links
]
return returnVal
getEventR::EventId->Handler值
getEventR eid=do
事件要执行此操作,您必须手动将实体
转换为值
,然后使用无序容器中的函数:Data.HashMap.Strict
插入“\u links”
键,然后再次从中构建值
。使用适用于aeson
的镜头兼容软件包可能会大大简化:
buildEntityWithLink :: Entity -> Text -> Maybe Value
buildEntityWithLink entity renderedUrl = case toJSON entity of
Object obj ->
let links = object ["self" .= renderedUrl]
entityWithLink = HashMap.insert "_links" links obj
in Just (Object entityWithLink)
_ -> Nothing
(我假设renderedUrl
的类型为Text
,如果需要可以更改)
然后,您只需传入您的实体
和rendereURL
,即可获得包含“\u links”
键的新值。我在这里使用了Maybe
来防止toJSON::Entity->Value
不使用对象
构造函数返回值的情况。如果您更改实体
类型及其转换为JSON的方式,但忘记更新所有代码库以反映此更改,这将在将来保护您
编辑:如果您要使用lens aeson
您可以这样写,尽管这需要交换参数顺序以保持整洁:
buildEntityWithLink :: Text -> Entity -> Value
buildEntityWithLink renderedUrl = (
over _Object $
HashMap.insert "_links" $
object ["self" .= renderedUrl]
) . toJSON
这实际上可以让您删除或者,您无论如何都想这样做,因为镜头的工作方式意味着,如果对象
不是顶层,则返回原始值,因此buildEntityWithLink“testlink”([]:[Entity])
将只返回与toJSON([]:[Entity])
相同的值,即一个空的数组
。toJSON
必须位于镜头操作的外部,因为为了与\u对象
组合,它必须能够成为一个setter,并且toJSON
不能轻易地成为setter。相反,我们只需将实体
预处理为值
,然后将其输入到镜头表达式中。我在每个函数的参数列表中添加了空格,使其在我看来更具可读性,但从技术上讲,这都是一行代码。此实现的一个有用特性是,现在可以轻松地将类型签名放宽为ToJSON A=>Text->A->Value
,这样您就可以将\u链接添加到任何想要添加的类型。要执行此操作,您必须手动将实体
转换为值,然后使用无序容器中的函数:Data.HashMap.Strict
插入“\u links”
键,然后再次从中构建一个值。使用适用于aeson
的镜头兼容软件包可能会大大简化:
buildEntityWithLink :: Entity -> Text -> Maybe Value
buildEntityWithLink entity renderedUrl = case toJSON entity of
Object obj ->
let links = object ["self" .= renderedUrl]
entityWithLink = HashMap.insert "_links" links obj
in Just (Object entityWithLink)
_ -> Nothing
(我假设renderedUrl
的类型为Text
,如果需要可以更改)
然后,您只需传入您的实体
和rendereURL
,即可获得包含“\u links”
键的新值。我在这里使用了Maybe
来防止toJSON::Entity->Value
不使用对象
构造函数返回值的情况。如果您更改实体
类型及其转换为JSON的方式,但忘记更新所有代码库以反映此更改,这将在将来保护您
编辑:如果您要使用lens aeson
您可以这样写,尽管这需要交换参数顺序以保持整洁:
buildEntityWithLink :: Text -> Entity -> Value
buildEntityWithLink renderedUrl = (
over _Object $
HashMap.insert "_links" $
object ["self" .= renderedUrl]
) . toJSON
这实际上可以让您删除或者,您无论如何都想这样做,因为镜头的工作方式意味着,如果对象
不是顶层,则返回原始值,因此buildEntityWithLink“testlink”([]:[Entity])
将只返回与toJSON([]:[Entity])
相同的值,即一个空的数组
。toJSON
必须位于镜头操作的外部,因为为了与\u对象
组合,它必须能够成为一个setter,并且toJSON
不能轻易地成为setter。相反,我们只需将实体
预处理为值
,然后将其输入到镜头表达式中。我在每个函数的参数列表中添加了空格,使其在我看来更具可读性,但从技术上讲,这都是一行代码。此实现的一个有用特性是,现在可以轻松地将类型签名放宽到ToJSON A=>Text->A->Value
,这样您就可以将\u链接添加到任何想要添加的类型。基于工作注释-这是我现在拥有的最后一个代码:
import Data.HashMap.Strict as HashMap (insert)
getEventR :: EventId -> Handler Value
getEventR eid = do
event <- runDB $ get404 eid
render <- getUrlRender
let renderedUrl = render $ EventR eid
let returnVal = object
[ "data" .= [buildEntityWithLink (Entity eid event) renderedUrl]]
return returnVal
buildEntityWithLink :: Entity Event -> Text -> Maybe Value
buildEntityWithLink entity renderedUrl =
case toJSON entity of
Object obj ->
let links = object ["self" .= renderedUrl]
entityWithLink = HashMap.insert "_links" links obj
in Just (Object entityWithLink)
_ -> Nothing
import Data.HashMap.Strict作为HashMap(插入)
getEventR::EventId->处理程序值
getEventR eid=do
事件可能值
buildEntityWithLink实体呈现URL=
case-toJSON实体
对象obj->
让links=object[“self”。=rendereURL]
entityWithLink=HashMap.insert“\u links”links obj
在Just中(对象entityWithLink)
_->没有
现在,根据工作注释,JSON以self
链接的形式出现,这是我现在拥有的最后一段代码:
import Data.HashMap.Strict as HashMap (insert)
getEventR :: EventId -> Handler Value
getEventR eid = do
event <- runDB $ get404 eid
render <- getUrlRender
let renderedUrl = render $ EventR eid
let returnVal = object
[ "data" .= [buildEntityWithLink (Entity eid event) renderedUrl]]
return returnVal
buildEntityWithLink :: Entity Event -> Text -> Maybe Value
buildEntityWithLink entity renderedUrl =
case toJSON entity of
Object obj ->
let links = object ["self" .= renderedUrl]
entityWithLink = HashMap.insert "_links" links obj
in Just (Object entityWithLink)
_ -> Nothing
import Data.HashMap.Strict作为HashMap(插入)
getEventR::EventId->处理程序值
getEventR eid=do
事件可能值
buildEntityWithLink实体呈现URL=
case-toJSON实体
对象obj->
让links=object[“self”。=rendereURL]
entityWithLink=HashMap.insert“\u links”links obj
在Just中(对象entityWithLink)
_->没有
事实上,现在JSON与self
链接一样出现了,谢谢。“使用