我有一条看起来像这样的记录:
data List a = List
{ list_count :: Int
, list__embedded :: [a]
-- ^The actual data you’re looking for.
}
deriving (Show)
list__embedded
字段来自外部API,其中嵌入实际上是一个对象:
{
"count": 5,
"_embedded": {
"payments": [
// payment records that derive FromJSON
]
}
}
如您所见,_embedded
字段实际上是一个对象,但是我只对它的值感兴趣。
我试图通过编写FromJSON
实现如下来解决该问题:
instance Aeson.FromJSON a => Aeson.FromJSON (List a) where
parseJSON (Aeson.Object v) = List
<$> Aeson.parseField v "count"
<*> fmap HashMap.elems (Aeson.parseField v "_embedded")
parseJSON invalid = Aeson.typeMismatch "Not a correct embed for a list" invalid
但是我一直遇到类型不匹配的情况:
• Could not deduce (Aeson.FromJSONKey k0)
arising from a use of ‘Aeson.parseField’
from the context: Aeson.FromJSON a
bound by the instance declaration
at src/Mollie/API/Types.hs:366:10-52
The type variable ‘k0’ is ambiguous
These potential instances exist:
instance Aeson.FromJSONKey Integer
-- Defined in ‘aeson-1.2.4.0:Data.Aeson.Types.FromJSON’
instance Aeson.FromJSONKey Text.Text
-- Defined in ‘aeson-1.2.4.0:Data.Aeson.Types.FromJSON’
instance Aeson.FromJSONKey Time.Day
-- Defined in ‘aeson-1.2.4.0:Data.Aeson.Types.FromJSON’
...plus 14 others
...plus 14 instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In the second argument of ‘fmap’, namely
‘(Aeson.parseField v "_embedded")’
In the second argument of ‘(<*>)’, namely
‘fmap HashMap.elems (Aeson.parseField v "_embedded")’
In the first argument of ‘(<*>)’, namely
‘List <$> Aeson.parseField v "count"
<*> fmap HashMap.elems (Aeson.parseField v "_embedded")’
|
369 | <*> fmap HashMap.elems (Aeson.parseField v "_embedded")
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
我不太确定如何进行这项工作。
答案 0 :(得分:0)
问题在于HashMap
的密钥类型不明确。即使您不使用键,Haskell仍需要知道类型,以便它可以确定要为Aeson.parseField v "_embedded"
调用实例化的解析器。您可以通过专门针对elems
的类型签名来帮助Haskell:
instance Aeson.FromJSON a => Aeson.FromJSON (List a) where
parseJSON (Aeson.Object v) = List
<$> Aeson.parseField v "count"
<*> fmap elems (Aeson.parseField v "_embedded")
where elems :: HashMap.HashMap Text.Text a -> [a]
elems = HashMap.elems
parseJSON invalid = Aeson.typeMismatch "Not a correct embed for a list" invalid
在此之后,我可以做:
> Aeson.decode "{\"count\": 5, \"_embedded\": {\"payments\": [1,2,3,4]}}"
:: Maybe (List [Double])
Just (List {list_count = 5, list__embedded = [[1.0,2.0,3.0,4.0]]})
我不确定您是否打算将付款清单设为list__embedded
的 ,但这应该可以使您走上正轨。