将 Json 个值的列表注入 HashMap
Inject a list of Json Values into a HashMap
我有一个 Product
引用了一个 Store
模型。
我想要 /stores/1
对 return 的响应 JSON 也有参考产品。类似于:
{
data: {
storeName: "Store1",
id: 1
products: {
{ productName : "Product1", productPrice: 10},
{ productName : "Product2", productPrice: 100},
}
}
}
我目前正忙于将产品注入正确的位置。
getStoreR :: StoreId -> Handler Value
getStoreR storeId = do
store <- runDB $ get404 storeId
products <- runDB $ selectList [StoreId ==. storeId] []
let productsJson = [entityIdToJSON (Entity k r) | Entity k r <- products]
let storeJson = entityIdToJSON (Entity storeId store)
-- Inject productsJson under "products" property fails
let storeJsonWithProducts = HM.insert "products" productsJson storeJson
return $ object ["data" .= storeJsonWithProducts]
失败:
Couldn't match expected type ‘HM.HashMap k0 [Value]’
with actual type ‘Value’
Relevant bindings include
storeJsonWithProducts :: HM.HashMap k0 [Value]
(bound at Main.hs:80:9)
In the third argument of ‘HM.insert’, namely ‘storeJson’
In the expression: HM.insert "products" productsJson storeJson
(顺便说一句,我用这个 here 创建了一个单文件应用程序)
HashMap.insert
的类型为 k -> v -> HashMap k v -> HashMap k v
。您的 storeJson
不是 HashMap
,而是 Value
——使用 Object :: HashMap Text Value -> Value
构造函数制作的。这意味着 v ~ Value
(如果您不熟悉,可以将 ~
理解为类型相等)。但是,这是一个问题,因为您的 productsJson
不是 Value
,而是 [Value]
。
因此,要解决您的问题,您需要:
从storeJson
中提取HashMap
。
let storeHM = case storeJson of
Object h -> h
当然,您应该确保正确处理此处的其他构造函数,因为如果 storeJson
不是用 Object
构造的,这将崩溃。
将 productJson
转换为 Value
。 Value
的构造函数之一是 Array :: Vector Value -> Value
,您可以使用 Data.Vector.fromList
:
从 [Value]
获得 Vector Value
import qualified Data.Vector as V
[...]
let productsValue = Array (V.fromList productsJson)
最后,将productsValue
插入storeHM
HashMap
:
let storeHMWithProducts = HM.insert "products" productsValue storeHM
然后您可以像以前一样继续操作,再次使用 object
将 storeHMWithProducts
转换为 JSON Value
:
return $ object ["data" .= storeHMWithProducts]
我有一个 Product
引用了一个 Store
模型。
我想要 /stores/1
对 return 的响应 JSON 也有参考产品。类似于:
{
data: {
storeName: "Store1",
id: 1
products: {
{ productName : "Product1", productPrice: 10},
{ productName : "Product2", productPrice: 100},
}
}
}
我目前正忙于将产品注入正确的位置。
getStoreR :: StoreId -> Handler Value
getStoreR storeId = do
store <- runDB $ get404 storeId
products <- runDB $ selectList [StoreId ==. storeId] []
let productsJson = [entityIdToJSON (Entity k r) | Entity k r <- products]
let storeJson = entityIdToJSON (Entity storeId store)
-- Inject productsJson under "products" property fails
let storeJsonWithProducts = HM.insert "products" productsJson storeJson
return $ object ["data" .= storeJsonWithProducts]
失败:
Couldn't match expected type ‘HM.HashMap k0 [Value]’
with actual type ‘Value’
Relevant bindings include
storeJsonWithProducts :: HM.HashMap k0 [Value]
(bound at Main.hs:80:9)
In the third argument of ‘HM.insert’, namely ‘storeJson’
In the expression: HM.insert "products" productsJson storeJson
(顺便说一句,我用这个 here 创建了一个单文件应用程序)
HashMap.insert
的类型为 k -> v -> HashMap k v -> HashMap k v
。您的 storeJson
不是 HashMap
,而是 Value
——使用 Object :: HashMap Text Value -> Value
构造函数制作的。这意味着 v ~ Value
(如果您不熟悉,可以将 ~
理解为类型相等)。但是,这是一个问题,因为您的 productsJson
不是 Value
,而是 [Value]
。
因此,要解决您的问题,您需要:
从
storeJson
中提取HashMap
。let storeHM = case storeJson of Object h -> h
当然,您应该确保正确处理此处的其他构造函数,因为如果
storeJson
不是用Object
构造的,这将崩溃。将
从productJson
转换为Value
。Value
的构造函数之一是Array :: Vector Value -> Value
,您可以使用Data.Vector.fromList
:[Value]
获得Vector Value
import qualified Data.Vector as V [...] let productsValue = Array (V.fromList productsJson)
最后,将
productsValue
插入storeHM
HashMap
:let storeHMWithProducts = HM.insert "products" productsValue storeHM
然后您可以像以前一样继续操作,再次使用 object
将 storeHMWithProducts
转换为 JSON Value
:
return $ object ["data" .= storeHMWithProducts]