使用Network-URI和Aeson,我定义了以下FROMJson URI
。
简而言之,我试图实现一个需要的JSON解码器:
{ "value" : X }
其中X
是一个JSON字符串,其parseURI(Just
)的评估结果为X
。
instance FromJSON URI where
parseJSON = withObject "URI" $ \v ->
case Data.HashMap.Lazy.lookup "value" v of
Just (String str) -> let unpacked = T.unpack str in
case parseURI unpacked of
Just uri -> pure uri
Nothing -> fail $ "String:" ++ unpacked ++ "is not a valid URI."
Just value -> typeMismatch "value" value
Nothing -> fail $ "JSON object does not have 'value' key."
但是,对于有效的URI
,我的代码无效:
λ: >parseURI "http://www.foo.com"
Just http://www.foo.com
λ: >toJSON $ URI "http" Nothing "//www.foo.com" "" ""
String "http//www.foo.com"
λ: >fromJSON $ toJSON $ URI "http" Nothing "//www.foo.com" "" ""
Error "expected (), encountered String"
如何修复我的FromJSON
实例?
答案 0 :(得分:2)
您的实例需要一个形状为{ "value": "url" }
的JSON对象,但您正在使用的toJSON
实例显然会产生一个纯字符串,因为您的交互式输出清楚地表明了这一点。
要使交互式会话中的最后一个表达式起作用,您需要使To
和From
个实例对称:或者让ToJSON
实例生成一个对象{ "value": "url" }
或者使FromJSON
实例期望一个普通的字符串。
另外,您可以使用.:
运算符以更短的方式表达您的实例:
instance FromJSON URI where
parseJSON = withObject "URI" $ \v -> do
mUri <- parseURI . T.unpack <$> v .: "value"
maybe (fail "Bad URI") pure mUri